<template>
    <div
        class="page_root"
        :key="queryUpdateFlag"
        data-page-name="平台用户故事&任务v2"
        data-page-identification="j_r4p6uatw7v"
    >
        <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
            <!-- begin vid_74h0kaeyby 自定义模板_ot1oz7qqmz -->
            <!--          关联需求-->
            <a-modal
                v-model:visible="milepostState.correlationVisible"
                title="关联需求"
                centered
                :mask-closable="false"
                :keyboard="false"
                @ok="confirmCorrelation"
                width="60%"
                @cancel="cancelCorrelation"
                :ok-button-props="{ loading: milepostState.correlationLoading }"
            >
                <div class="transfer-tip">
                    当需求池需求编号和手动创建用户故事需求编号不同时，关联二者后将展示需求池编号；<br />
                    当关联通过转化生成的用户故事时，多个需求编号将同时展示于用户故事中；
                </div>
                <div class="table-title">已关联需求（勾选后提交可取消关联）</div>
                <div class="correlation-box">
                    <a-table
                        bordered
                        :columns="correlationColumns"
                        :data-source="milepostState.correlationData"
                        row-key="requirementId"
                        :loading="milepostState.correlationTableLoading"
                        :rowSelection="{
                            selectedRowKeys: milepostState.correlationSelectKeys,
                            onChange: onSelectChange
                        }"
                        :pagination="false"
                    />
                </div>
                <a-form-item label="关联新需求">
                    <a-select
                        v-model:value="milepostState.correlationNewData"
                        :options="milepostState.allDemand"
                        :filterOption="
                            (input, option) => {
                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                            }
                        "
                        mode="multiple"
                        @focus="getAllDemand"
                        show-search
                        allow-clear
                    />
                </a-form-item>
            </a-modal>
            <!--          关联需求-->
            <!--          用户故事转移-->
            <a-modal
                v-model:visible="milepostState.transferVisible"
                title="转移"
                centered
                :mask-closable="false"
                :keyboard="false"
                @ok="confirmTransfer"
                @cancel="cancelTransfer"
                :ok-button-props="{ loading: milepostState.transferLoading }"
            >
                <div class="transfer-tip">
                    请选择转移至具体迭代项目 <br />
                    转移以后当前项目不再展示该用户故事
                </div>
                <a-form-item label="迭代项目" style="margin-top: 16px">
                    <a-tree-select
                        show-search
                        style="width: 100%"
                        placeholder="请选择"
                        allow-clear
                        treeDefaultExpandAll
                        :fieldNames="{
                            children: 'children',
                            label: 'projectName',
                            value: 'projectId',
                            key: 'projectId'
                        }"
                        v-model:value="milepostState.transferId"
                        :tree-data="milepostState.projectTreeDate"
                    />
                </a-form-item>
            </a-modal>
            <!--          用户故事转移-->
            <!--          任务/用户故事概览-->
            <a-drawer
                v-model:visible="descriptionState.visible"
                @close="cancelDescription"
                :title="descriptionState.title"
                placement="right"
                :maskClosable="false"
                :keyboard="false"
                width="720"
            >
                <div class="description-title">基本信息</div>

                <div class="desc-wrapper" v-if="descriptionState.type === '故事'">
                    <table class="desc-table">
                        <colgroup>
                            <col style="width: 120px" />
                            <col />
                            <col style="width: 120px" />
                            <col />
                        </colgroup>
                        <tbody>
                            <!-- 占整行 -->
                            <tr>
                                <th>用户故事名称</th>
                                <td colspan="3">{{ descriptionState.description.storyName || '-' }}</td>
                            </tr>

                            <!-- 占整行 -->
                            <tr>
                                <th>所属子目标</th>
                                <td colspan="3">{{ descriptionState.description.projectMonthlyGoal || '-' }}</td>
                            </tr>

                            <!-- 每行两组 label:value -->
                            <tr>
                                <th>版本号</th>
                                <td>{{ descriptionState.description.iterationVersionName || '-' }}</td>
                                <th>用户故事状态</th>
                                <td>{{ descriptionState.description.storyStatus || '-' }}</td>
                            </tr>

                            <tr>
                                <th>标签</th>
                                <td>{{ descriptionState.description.labels || '-' }}</td>
                                <th>进度</th>
                                <td>
                                    <a-tooltip>
                                        <template #title>
                                            <div>
                                                <div>任务总数{{ descriptionState.description.taskNumber }}个</div>
                                                <div class="flex-color">
                                                    <div class="no-start"></div>
                                                    <div
                                                        >未开始任务数{{
                                                            descriptionState.description.noStartTaskNumber
                                                        }}个</div
                                                    >
                                                </div>
                                                <div class="flex-color">
                                                    <div class="running"></div>
                                                    <div
                                                        >进行中任务数{{
                                                            descriptionState.description.runningTaskNumber
                                                        }}个</div
                                                    >
                                                </div>
                                                <div class="flex-color">
                                                    <div class="finish"></div>
                                                    <div
                                                        >已完成任务数{{
                                                            descriptionState.description.finishTaskNumber
                                                        }}个</div
                                                    >
                                                </div>
                                            </div>
                                        </template>
                                        <div style="display: flex; gap: 8px">
                                            <a-progress
                                                style="width: 130px"
                                                :percent="totalPercent(descriptionState.description)"
                                                :success="{
                                                    percent: finishPercent(descriptionState.description),
                                                    strokeColor: '52c41a'
                                                }"
                                                :show-info="false"
                                                trailColor="#d9d9d9"
                                                strokeColor="#3875ff"
                                            />
                                            <div
                                                >{{
                                                    formatPercentage(
                                                        descriptionState.description.taskNumber
                                                            ? (descriptionState.description.finishTaskNumber /
                                                                  descriptionState.description.taskNumber) *
                                                                  100
                                                            : 0
                                                    )
                                                }}%</div
                                            >
                                        </div>
                                    </a-tooltip>
                                </td>
                            </tr>

                            <tr>
                                <th>优先级</th>
                                <td>{{ descriptionState.description.priority || '-' }}</td>
                                <th>负责人</th>
                                <td>{{ descriptionState.description.owner || '-' }}</td>
                            </tr>

                            <tr>
                                <th>计划开始</th>
                                <td>{{ descriptionState.description.startTime || '-' }}</td>
                                <th>实际开始</th>
                                <td>{{ descriptionState.description.actualStartTime || '-' }}</td>
                            </tr>

                            <tr>
                                <th>计划完成</th>
                                <td>{{ descriptionState.description.endTime || '-' }}</td>
                                <th>实际完成</th>
                                <td>{{ descriptionState.description.actualEndTime || '-' }}</td>
                            </tr>

                            <tr>
                                <th>创建人</th>
                                <td>{{ descriptionState.description.createdBy || '-' }}</td>
                                <th>创建时间</th>
                                <td>{{ descriptionState.description.createdTime || '-' }}</td>
                            </tr>
                        </tbody>
                    </table>
                    <div class="description-title">描述</div>
                    <div v-html="getHtmlContent(descriptionState.description.description)"></div>
                    <div class="description-title">最新备注</div>
                    <div>{{ descriptionState.description.remarks }}</div>
                </div>
                <div class="desc-wrapper" v-else>
                    <table class="desc-table">
                        <colgroup>
                            <col style="width: 120px" />
                            <col />
                            <col style="width: 120px" />
                            <col />
                        </colgroup>
                        <tbody>
                            <!-- 占整行 -->
                            <tr>
                                <th class="description-label">任务名称</th>
                                <td colspan="3">{{ descriptionState.description.storyName || '-' }}</td>
                            </tr>

                            <!-- 占整行 -->

                            <!-- 每行两组 label:value -->
                            <tr>
                                <th>任务状态</th>
                                <td>{{ descriptionState.description.taskStatus || '-' }}</td>
                                <th>优先级</th>
                                <td>{{ descriptionState.description.priority || '-' }}</td>
                            </tr>

                            <tr>
                                <th>负责人</th>
                                <td>{{ descriptionState.description.taskOwner || '-' }}</td>
                                <th>审核员</th>
                                <td>{{ descriptionState.description.assessorName || '-' }}</td>
                            </tr>

                            <tr>
                                <th>执行人</th>
                                <td colspan="3">{{ descriptionState.description.taskParticipant || '-' }}</td>
                            </tr>

                            <tr>
                                <th>计划开始</th>
                                <td>{{ descriptionState.description.startTime || '-' }}</td>
                                <th>实际开始</th>
                                <td>{{ descriptionState.description.examPassTime || '-' }}</td>
                            </tr>

                            <tr>
                                <th>计划完成</th>
                                <td>{{ descriptionState.description.endTime || '-' }}</td>
                                <th>实际完成</th>
                                <td>{{ descriptionState.description.taskFinishTime || '-' }}</td>
                            </tr>
                            <tr>
                                <th>计划工时</th>
                                <td>{{ descriptionState.description.workingHours || '-' }}</td>
                                <th>实际工时</th>
                                <td>{{ descriptionState.description.actualWorkHours || '-' }}</td>
                            </tr>

                            <tr>
                                <th>创建人</th>
                                <td>{{ descriptionState.description.createBy || '-' }}</td>
                                <th>创建时间</th>
                                <td>{{ descriptionState.description.createTime || '-' }}</td>
                            </tr>
                        </tbody>
                    </table>
                    <div class="description-title">审核标准</div>
                    <div class="description-body">{{ descriptionState.description.assessorStandard }}</div>
                    <div class="description-title">附件模板</div>
                    <div
                        class="description-body"
                        v-for="(item, index) in descriptionState.description.attachmentTemplateList"
                        :key="index"
                        @click="handlerDownload(item)"
                    >
                        {{ item.name }}
                    </div>
                    <div class="description-title">附件</div>
                    <div
                        class="description-body"
                        v-for="(item, index) in descriptionState.description.attachmentList"
                        :key="index"
                        @click="handlerDownload(item)"
                    >
                        {{ item.name }}
                    </div>
                    <div class="description-title">最新备注</div>
                    <div>{{ descriptionState.description.description }}</div>
                </div>
            </a-drawer>

            <!--          任务/用户故事概览-->
            <!--          任务相关弹窗=================================================================================-->
            <!--            查看问题-->
            <a-modal
                :visible="showMsgState.visible"
                title="问题描述"
                :footer="null"
                centered
                :mask-closable="false"
                :keyboard="false"
                @cancel="cancelShowMsg"
                width="1000px"
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
            >
                <div class="item-content" v-html="getHtmlContent(showMsgState.msg)"> </div>
            </a-modal>
            <!--            查看问题-->

            <!--          流转变更-->
            <a-modal
                centered
                v-model:visible="taskState.culaVisible"
                title="流转"
                width="520px"
                :mask-closable="false"
                :keyboard="false"
                @ok="handleSubmitCirculation"
                destroy-on-close
                :body-style="{
                    paddingBottom: 0
                }"
                :ok-button-props="{
                    loading: taskState.culaLoading
                }"
                @cancel="cancelCirculation"
            >
                <div class="change-status">
                    <a-row>
                        <a-col :span="24">
                            <a-form-item
                                label="解决人"
                                :rules="[{ required: true, message: '请选择解决人', trigger: 'blur' }]"
                                name="solverList"
                            >
                                <a-select
                                    :placeholder="selectHolder"
                                    :options="groupList"
                                    :allowClear="true"
                                    :dropdownMatchSelectWidth="true"
                                    :showSearch="true"
                                    :filterOption="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    :max-tag-count="1"
                                    :showArrow="true"
                                    v-model:value="taskState.culaPeople"
                                />
                            </a-form-item>
                        </a-col>
                    </a-row>
                </div>
            </a-modal>
            <!--          流转变更-->
            <!--审批详情-->
            <a-modal
                @cancel="statuState.visible = false"
                centered
                :mask-closable="false"
                :keyboard="false"
                :visible="statuState.visible"
                title="审批详情"
                @ok="handleConfirmStatus"
                :body-style="{ maxHeight: '700px', overflowY: 'auto' }"
                width="400px"
            >
                <div style="margin-bottom: 16px"
                    >任务名称：<span style="color: #262626">{{ statuState.taskName }}</span>
                </div>
                <a-radio-group v-model:value="statusRadio" button-style="solid" style="margin-bottom: 16px">
                    <a-radio-button value="状态变更">状态变更</a-radio-button>
                    <a-radio-button value="审批记录">审批记录</a-radio-button>
                </a-radio-group>
                <template v-if="statusRadio === '审批记录'">
                    <div class="status-item" v-for="(item, index) in statuState.list">
                        <div class="title-new-status">
                            <div class="left-title"
                                >审批类型:<span class="weight-status-new">{{ item.processName }} </span></div
                            >
                            <div class="right-title"
                                >审批提交时间:<span class="weight-status-new">{{ item.createdDate }} </span></div
                            >
                        </div>
                        <a-steps class="status-step" direction="vertical">
                            <a-step
                                v-for="(inside, index) in item.processTaskList"
                                :title="inside.nodeMessage"
                                :description="inside.taskName + ':' + inside.assignUserName"
                                :status="getIconStatus(inside.nodeStatus)"
                            />
                        </a-steps>
                    </div>
                </template>
                <template v-else>
                    <div>
                        <a-radio-group v-model:value="statusCheckList" style="margin-bottom: 16px">
                            <a-row>
                                <a-col :span="24" v-for="(item, index) in statusList">
                                    <a-radio :value="item">{{ item }}</a-radio>
                                </a-col>
                            </a-row>
                        </a-radio-group>
                    </div>
                </template>
            </a-modal>

            <!--审批详情-->
            <!--         备注   -->
            <a-modal
                :visible="noteState.visibleNotes"
                title="备注"
                width="70vw"
                centered
                destroyOnClose
                :mask-closable="false"
                :keyboard="false"
                :footer="null"
                :getContainer="getModalContainer"
                @cancel="cancelNotice"
            >
                <div class="history-remark-title">
                    <a-button type="primary" @click="handleAddRemark" v-permission="'50001252_vid_966s16bwvw'"
                        >新建</a-button
                    >
                </div>
                <a-table
                    class="note-table"
                    bordered
                    rowKey="taskId"
                    :customRow="customRow"
                    :columns="noteState.notesColumns"
                    :data-source="noteState.noteData"
                    :pagination="false"
                    :scroll="{ y: 600 }"
                    :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
                >
                    <template #bodyCell="{ column, record, index }">
                        <template v-if="column.dataIndex === 'description'">
                            <a-textarea v-if="record.editing" v-model:value="record.description" placeholder="请输入" />
                            <span v-else>{{ record.description }}</span>
                        </template>

                        <template v-else-if="column.dataIndex === 'operation'">
                            <a-space>
                                <a-button
                                    v-if="record.editing"
                                    type="link"
                                    size="small"
                                    :loading="record.okBtnLoading"
                                    @click="handleSaveRemark(record)"
                                    >完成</a-button
                                >
                                <a-button
                                    v-if="record.editing"
                                    type="link"
                                    size="small"
                                    @click="handleCancelRemark(record, index)"
                                    >取消</a-button
                                >
                                <a-button
                                    v-if="!record.editing"
                                    type="link"
                                    size="small"
                                    @click="handleEditRemark(record)"
                                    v-permission="'50001252_vid_sga4caktmb'"
                                >
                                    编辑
                                </a-button>
                                <a-popconfirm
                                    title="确认删除该行吗？"
                                    @confirm="handleDeleteRemark(record.descriptionId, index)"
                                >
                                    <a-button
                                        v-if="!record.editing"
                                        type="link"
                                        size="small"
                                        v-permission="'50001252_vid_rdxivyknic'"
                                    >
                                        删除
                                    </a-button>
                                </a-popconfirm>
                            </a-space>
                        </template>
                    </template>
                </a-table>
            </a-modal>
            <!--         备注   -->
            <!--         变更记录   -->
            <a-modal
                :visible="changeLogState.visible"
                title="变更记录"
                width="70vw"
                centered
                destroyOnClose
                :mask-closable="false"
                :keyboard="false"
                :footer="null"
                :getContainer="getModalContainer"
                @cancel="cancelChangeLog"
            >
                <a-table
                    class="note-table"
                    bordered
                    rowKey="taskId"
                    :customRow="customRow"
                    :columns="changeLogColumns"
                    :scroll="{ y: 600 }"
                    :data-source="changeLogState.dataSource"
                    :pagination="false"
                    :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
                />
            </a-modal>
            <!--         变更记录   -->
            <!--                      模板项目-风险预警-->
            <a-modal
                v-model:visible="warnState.warringVisible"
                title="新增任务风险"
                @ok="handleTemplateRiskOk"
                :mask-closable="false"
                :keyboard="false"
            >
                <a-form :model="warnState.templateRisk" ref="templateRiskRef">
                    <a-row>
                        <a-col :span="24">
                            <a-form-item
                                label="任务名称"
                                name="taskName"
                                :rules="[{ required: true, message: '请输入任务名称', trigger: 'blur' }]"
                            >
                                <a-input
                                    v-model:value="warnState.templateRisk.taskName"
                                    disabled
                                    :placeholder="inputHolder"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="24">
                            <a-form-item
                                label="风险描述"
                                name="riskDescription"
                                :rules="[{ required: true, message: '请输入风险描述', trigger: 'blur' }]"
                            >
                                <a-input
                                    v-model:value="warnState.templateRisk.riskDescription"
                                    :placeholder="inputHolder"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="24">
                            <a-form-item
                                label="解决方案"
                                name="solution"
                                :rules="[{ required: true, message: '请输入解决方案', trigger: 'blur' }]"
                            >
                                <a-input v-model:value="warnState.templateRisk.solution" :placeholder="inputHolder" />
                            </a-form-item>
                        </a-col>
                    </a-row>
                </a-form>
            </a-modal>
            <!--                      end模板项目-风险预警-->
            <!--            提测/验收-->
            <a-modal
                :visible="taskState.checkVisible"
                :title="taskState.checkTitle"
                @ok="handleSubmitCheck"
                @cancel="cancelCheck"
                :mask-closable="false"
                :keyboard="false"
                centered
                :ok-button-props="{ loading: taskState.checkLoading }"
            >
                <div>请确认该任务是否需要{{ checkFlag }}</div>
                <div
                    >提交{{ checkFlag }}后，手动编辑的状态将自动变更为{{
                        checkFlag === '提测' ? '测试中' : '验收中'
                    }}</div
                >
                <div>并且向{{ checkFlag === '提测' ? '测试经理' : '产品经理' }}发送通知</div>
            </a-modal>
            <!--            提测/验收-->
            <!-- 新-模板项目检查清单弹出框 -->
            <a-modal
                :visible="taskState.okMbVisible"
                title="完成任务"
                destroyOnClose
                centered
                width="40%"
                :mask-closable="false"
                :keyboard="false"
                :getContainer="getModalContainer"
                @cancel="taskState.okMbVisible = false"
            >
                <a-form-item label="实际完成时间">
                    <a-date-picker v-model:value="finishTimeSubmit" value-format="YYYY-MM-DD" />
                </a-form-item>
                <div
                    style="border-bottom: 1px solid #d9d9d9; margin-bottom: 10px"
                    v-if="taskState.ppmTemplateCheckList.length > 0 || taskState.sopList[0].contentList.length > 0"
                >
                    <!-- 完成标准 -->
                    <div class="new-check" v-if="taskState.ppmTemplateCheckList.length > 0">
                        <div class="label">审核标准</div>
                    </div>
                    <div class="checkbox-group" v-for="(item, index) in taskState.ppmTemplateCheckList" :key="index">
                        <a-checkbox v-model:checked="item.selected">
                            {{ item.content }}
                        </a-checkbox>
                    </div>
                    <!--                        sop-->
                    <div class="new-check" v-if="taskState.sopList[0].contentList.length > 0">
                        <div class="label">SOP</div>
                    </div>
                    <div class="checkbox-group">
                        <a-checkbox
                            v-for="(msg, index) in taskState.sopList[0].contentList"
                            :key="index"
                            v-model:checked="msg.selected"
                        >
                            {{ msg.msg }}
                        </a-checkbox>
                    </div>
                    <!--                        sop-->
                </div>

                <template #footer>
                    <a-button
                        key="back"
                        type="primary"
                        @click="downLoadTemplate"
                        v-if="currentOkTask.templateFlag === '是'"
                        >下载模板</a-button
                    >
                    <a-button key="back" @click="taskState.okMbVisible = false">取消</a-button>
                    <a-button key="back" @click="handleSubmitSop" v-if="currentOkTask.templateFlag === '是'"
                        >暂存SOP</a-button
                    >
                    <a-button key="submit" type="primary" :loading="templateOkDisabled" @click="handlerTemplateOk"
                        >提交审批</a-button
                    >
                </template>
                <a-spin :spinning="uploadLoading">
                    <a-upload
                        :file-list="taskState.fileList"
                        :multiple="true"
                        :before-upload="handlerUploadWc"
                        @remove="handleRemoveWc"
                        accept=".xlsx,.ppt,.pdf,.PDF, image/*, .docx, .rp, .xls"
                    >
                        <a-button type="primary">
                            <upload-outlined />
                            上传
                        </a-button>
                    </a-upload>
                    <span>支持格式：image/*,.xlsx,.xls,.docx,.rp,.ppt,.pptx,.pdf</span>
                </a-spin>
            </a-modal>
            <!-- 模板项目检查清单弹出框 -->
            <!--                  预览-->
            <a-modal
                v-model:visible="stateF.previewVisible"
                @cancel="handleCancel"
                width="1000px"
                title="图片预览"
                :footer="null"
                :mask-closable="false"
                :keyboard="false"
            >
                <div v-if="stateF.isImagePreview">
                    <img :src="stateF.previewImage" alt="附件" style="width: 100%" />
                </div>
                <div v-else>
                    <iframe :src="stateF.previewFileUrl" style="width: 100%; height: 500px"></iframe>
                </div>
            </a-modal>
            <!--                  预览-->
            <!--                  操作附件-->
            <a-modal
                :visible="showFileVisible"
                title="附件"
                :footer="null"
                :mask-closable="false"
                :keyboard="false"
                @cancel="showFileCancel"
                centered
                :maskClosable="false"
            >
                <div v-for="(item, index) in fileShowList" :key="index" class="file-item">
                    <a-dropdown>
                        <span
                            style="overflow: hidden; white-space: nowrap; text-overflow: ellipsis; display: block"
                            :title="item.name"
                        >
                            {{ item.name }}
                        </span>
                        <template #overlay>
                            <a-menu>
                                <a-menu-item>
                                    <a-button
                                        style="width: 100%"
                                        type="link"
                                        size="small"
                                        :disabled="!item.type.startsWith('image')"
                                        @click="previewAttachment(item)"
                                        >预览</a-button
                                    >
                                </a-menu-item>
                                <a-menu-item>
                                    <a-button
                                        style="width: 100%"
                                        type="link"
                                        size="small"
                                        @click="handlerDownload(item)"
                                        >下载</a-button
                                    >
                                </a-menu-item>
                            </a-menu>
                        </template>
                    </a-dropdown>
                </div>
            </a-modal>
            <!--                  操作附件-->
            <!--          编辑任务-->
            <a-modal
                :visible="taskState.editTaskVisible"
                :title="taskState.editTaskTitle"
                centered
                width="1000px"
                @ok="confirmEditOtherMb"
                :ok-button-props="{ loading: taskState.editTaskLoading }"
                @cancel="cancelEditTask"
                destroy-on-close
                :mask-closable="false"
                :keyboard="false"
            >
                <div class="mbtask-form">
                    <a-form :model="taskState.editTaskForm" ref="ptOtherRef">
                        <div v-for="(item, index) in taskState.editTaskForm.taskList" :key="index" class="form-item">
                            <a-row>
                                <a-col :span="24">
                                    <a-form-item
                                        label="任务名称"
                                        :name="['taskList', index, 'taskName']"
                                        :rules="[
                                            {
                                                required: true,
                                                message: '请输入任务名称!'
                                            },
                                            {
                                                validator: () => {
                                                    if (taskState.editTaskForm.taskList[index].taskName) {
                                                        if (taskState.editTaskForm.taskList[index].taskName.trim()) {
                                                            return PromiseProxy.resolve()
                                                        } else {
                                                            return PromiseProxy.reject('请输入任务名称!')
                                                        }
                                                    } else {
                                                        return PromiseProxy.resolve()
                                                    }
                                                }
                                            }
                                        ]"
                                    >
                                        <a-input
                                            :placeholder="inputHolder"
                                            v-model:value="taskState.editTaskForm.taskList[index].taskName"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="24">
                                    <a-form-item
                                        label="所属用户故事"
                                        :name="['taskList', index, 'storyId']"
                                        :rules="{ required: true, message: '请选择所属用户故事!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.editTaskForm.taskList[index].storyId"
                                            showSearch
                                            :options="taskState.storyList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @focus="getStory"
                                            @change="taskState.editTaskForm.taskList[index].parentId = undefined"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12">
                                    <!--                                    <a-form-item label="所属SOP任务">-->
                                    <!--                                        <a-tree-select-->
                                    <!--                                            :disabled="!currentOtherTask.taskId"-->
                                    <!--                                            placeholder="请选择所属SOP任务"-->
                                    <!--                                            v-model:value="taskState.editTaskForm.taskList[index].parentId"-->
                                    <!--                                            allowClear-->
                                    <!--                                            showSearch-->
                                    <!--                                            :tree-data="taskState.editSopTaskList"-->
                                    <!--                                            :field-names="{ label: 'taskName', value: 'taskId' }"-->
                                    <!--                                            :filter-option="-->
                                    <!--                                                (input, option) => {-->
                                    <!--                                                    return (-->
                                    <!--                                                        option.taskName.toLowerCase().indexOf(input.toLowerCase()) >= 0-->
                                    <!--                                                    )-->
                                    <!--                                                }-->
                                    <!--                                            "-->
                                    <!--                                            @focus="getEditSopTask"-->
                                    <!--                                        />-->
                                    <!--                                    </a-form-item>-->
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="12">
                                    <a-form-item
                                        label="计划起止时间"
                                        :name="['taskList', index, 'allTime']"
                                        :rules="{ required: true, message: '请选择计划起止时间!' }"
                                    >
                                        <a-range-picker
                                            style="width: 100%"
                                            v-model:value="taskState.editTaskForm.taskList[index].allTime"
                                            value-format="YYYY-MM-DD"
                                            @change="getCurrentTaskParticipantList('editTaskForm', index)"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12">
                                    <a-form-item
                                        label="任务负责人"
                                        :name="['taskList', index, 'taskOwner']"
                                        :rules="{ required: true, message: '请选择任务负责人!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.editTaskForm.taskList[index].taskOwner"
                                            showSearch
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @change="getCurrentTaskParticipantList('editTaskForm', index)"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12" v-if="currentmubanTask.taskId">
                                    <a-form-item
                                        label="实际开始时间"
                                        :name="['taskList', index, 'examPassTime']"
                                        :rules="{ required: false, message: '请选择实际开始时间!' }"
                                    >
                                        <a-date-picker
                                            :disabled="!currentmubanTask.examPassTime"
                                            style="width: 100%"
                                            v-model:value="taskState.editTaskForm.taskList[index].examPassTime"
                                            valueFormat="YYYY-MM-DD"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12" v-if="currentmubanTask.taskId">
                                    <a-form-item
                                        label="实际完成时间"
                                        :name="['taskList', index, 'taskFinishTime']"
                                        :rules="{ required: false, message: '请选择实际完成!' }"
                                    >
                                        <a-date-picker
                                            :disabled="!currentmubanTask.taskFinishTime"
                                            style="width: 100%"
                                            v-model:value="taskState.editTaskForm.taskList[index].taskFinishTime"
                                            valueFormat="YYYY-MM-DD"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12" v-if="currentOtherTask.taskId">
                                    <a-form-item
                                        label="实际开始时间"
                                        :name="['taskList', index, 'examPassTime']"
                                        :rules="{ required: false, message: '请选择实际开始时间!' }"
                                    >
                                        <a-date-picker
                                            :disabled="!currentOtherTask.examPassTime"
                                            style="width: 100%"
                                            v-model:value="taskState.editTaskForm.taskList[index].examPassTime"
                                            valueFormat="YYYY-MM-DD"
                                            :allow-clear="!currentOtherTask.examPassTime"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12" v-if="currentOtherTask.taskId">
                                    <a-form-item
                                        label="实际完成时间"
                                        :name="['taskList', index, 'taskFinishTime']"
                                        :rules="{ required: false, message: '请选择实际完成!' }"
                                    >
                                        <a-date-picker
                                            :disabled="!currentOtherTask.taskFinishTime"
                                            style="width: 100%"
                                            v-model:value="taskState.editTaskForm.taskList[index].taskFinishTime"
                                            valueFormat="YYYY-MM-DD"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="12">
                                    <a-form-item
                                        label="审核员"
                                        :name="['taskList', index, 'assessorName']"
                                        :rules="{ required: false, message: '请选择审核员!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.editTaskForm.taskList[index].assessorName"
                                            showSearch
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="12">
                                    <a-form-item label="优先级">
                                        <a-select
                                            :options="[
                                                {
                                                    label: 'P0',
                                                    value: 'P0'
                                                },
                                                {
                                                    label: 'P1',
                                                    value: 'P1'
                                                },
                                                {
                                                    label: 'P2',
                                                    value: 'P2'
                                                },
                                                {
                                                    label: 'P3',
                                                    value: 'P3'
                                                }
                                            ]"
                                            v-model:value="taskState.editTaskForm.taskList[index].priority"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="24">
                                    <a-form-item
                                        label="任务执行人"
                                        :name="['taskList', index, 'taskParticipantList']"
                                        :rules="{ required: true, message: '请选择任务参与人!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.editTaskForm.taskList[index].taskParticipantList"
                                            showSearch
                                            mode="multiple"
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @change="getCurrentTaskParticipantList('editTaskForm', index)"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col v-if="taskPeopleList.length > 0" :span="24">
                                    <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                                        <a
                                            href="javascript:;"
                                            v-for="(item, num) in taskPeopleList"
                                            @click="handlerAddEditPeople(item.value, index)"
                                            ><span style="margin: 0 5px">{{ item.value }}</span></a
                                        >
                                    </div>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="24">
                                    <a-form-item
                                        label="预计投入工时"
                                        :name="['taskList', index, 'workingHours']"
                                        :rules="[
                                            { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                            {
                                                pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                message: '请输入大于0的数字(支持0.5的倍数)',
                                                trigger: 'blur'
                                            }
                                        ]"
                                    >
                                        <a-input
                                            placeholder="请输入工时(支持0.5的数字)"
                                            v-model:value="taskState.editTaskForm.taskList[index].workingHours"
                                            :min="0"
                                            type="number"
                                            suffix="小时"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                        </div>
                    </a-form>
                </div>
            </a-modal>
            <!--          编辑任务-->
            <!--          新建子任务-->
            <a-modal
                :visible="taskState.otherTaskVisible"
                :title="taskState.otherTaskTitle"
                centered
                width="1000px"
                :mask-closable="false"
                :keyboard="false"
                @ok="confirmOtherMb"
                :ok-button-props="{ loading: taskState.otherOkLoading }"
                @cancel="cancelOtherMb"
                destroy-on-close
            >
                <div class="mbtask-form">
                    <a-form :model="taskState.otherTaskForm" ref="ptOtherRef">
                        <div v-for="(item, index) in taskState.otherTaskForm.taskList" :key="index" class="form-item">
                            <a-row>
                                <a-col :span="22">
                                    <a-form-item
                                        label="任务名称"
                                        :name="['taskList', index, 'taskName']"
                                        :rules="[
                                            {
                                                required: true,
                                                message: '请输入任务名称!'
                                            },
                                            {
                                                validator: () => {
                                                    if (taskState.otherTaskForm.taskList[index].taskName) {
                                                        if (taskState.otherTaskForm.taskList[index].taskName.trim()) {
                                                            return PromiseProxy.resolve()
                                                        } else {
                                                            return PromiseProxy.reject('请输入任务名称!')
                                                        }
                                                    } else {
                                                        return PromiseProxy.resolve()
                                                    }
                                                }
                                            }
                                        ]"
                                    >
                                        <a-input
                                            :placeholder="inputHolder"
                                            v-model:value="taskState.otherTaskForm.taskList[index].taskName"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="2"
                                    ><a-button type="link" @click="handleDeleteOtherItem(index)"> 删除</a-button>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="22">
                                    <a-form-item
                                        label="所属用户故事"
                                        :name="['taskList', index, 'storyId']"
                                        :rules="{ required: true, message: '请选择所属用户故事!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.otherTaskForm.taskList[index].storyId"
                                            showSearch
                                            :options="taskState.storyList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @change="
                                                taskState.otherTaskForm.taskList[index].priority = getPriorityByStory(
                                                    taskState.otherTaskForm.taskList[index].storyId
                                                )
                                            "
                                            @focus="getStory"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>

                            <a-row>
                                <a-col :span="11">
                                    <a-form-item
                                        label="计划起止时间"
                                        :name="['taskList', index, 'allTime']"
                                        :rules="{ required: true, message: '请选择计划起止时间!' }"
                                    >
                                        <a-range-picker
                                            style="width: 100%"
                                            v-model:value="taskState.otherTaskForm.taskList[index].allTime"
                                            valueFormat="YYYY-MM-DD"
                                            @change="getCurrentTaskParticipantList('otherTaskForm', index)"
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="11">
                                    <a-form-item
                                        label="任务负责人"
                                        :name="['taskList', index, 'taskOwner']"
                                        :rules="{ required: true, message: '请选择任务负责人!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.otherTaskForm.taskList[index].taskOwner"
                                            showSearch
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @change="getCurrentTaskParticipantList('otherTaskForm', index)"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="11">
                                    <a-form-item label="审核员">
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.otherTaskForm.taskList[index].assessorName"
                                            showSearch
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                        />
                                    </a-form-item>
                                </a-col>
                                <a-col :span="11">
                                    <a-form-item label="优先级">
                                        <a-select
                                            :options="[
                                                {
                                                    label: 'P0',
                                                    value: 'P0'
                                                },
                                                {
                                                    label: 'P1',
                                                    value: 'P1'
                                                },
                                                {
                                                    label: 'P2',
                                                    value: 'P2'
                                                },
                                                {
                                                    label: 'P3',
                                                    value: 'P3'
                                                }
                                            ]"
                                            v-model:value="taskState.otherTaskForm.taskList[index].priority"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="22">
                                    <a-form-item
                                        label="任务执行人"
                                        :name="['taskList', index, 'taskParticipantList']"
                                        :rules="{ required: true, message: '请选择任务参与人!' }"
                                    >
                                        <a-select
                                            :placeholder="selectHolder"
                                            v-model:value="taskState.otherTaskForm.taskList[index].taskParticipantList"
                                            showSearch
                                            mode="multiple"
                                            :options="peopleList"
                                            :field-names="{ label: 'label', value: 'value' }"
                                            :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                                            @change="getCurrentTaskParticipantList('otherTaskForm', index)"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col v-if="taskPeopleList.length > 0" :span="22">
                                    <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                                        <a
                                            href="javascript:;"
                                            v-for="(item, num) in taskPeopleList"
                                            @click="handlerAddOtherPeople(item.value, index)"
                                            ><span style="margin: 0 5px">{{ item.value }}</span></a
                                        >
                                    </div>
                                </a-col>
                            </a-row>
                            <a-row>
                                <a-col :span="22">
                                    <a-form-item
                                        label="预计投入工时"
                                        :name="['taskList', index, 'workingHours']"
                                        :rules="[
                                            { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                            {
                                                pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                message: '请输入大于0的数字(支持0.5的倍数)',
                                                trigger: 'blur'
                                            }
                                        ]"
                                    >
                                        <a-input
                                            placeholder="请输入工时(支持0.5的数字)"
                                            v-model:value="taskState.otherTaskForm.taskList[index].workingHours"
                                            :min="0"
                                            type="number"
                                            suffix="小时"
                                        />
                                    </a-form-item>
                                </a-col>
                            </a-row>
                        </div>
                        <a-col :span="22">
                            <a-button @click="handleAddOtherItem" type="primary" ghost> 新增</a-button>
                        </a-col>
                    </a-form>
                </div>
            </a-modal>
            <!--          新建子任务-->
            <!--            新建sop任务-->
            <a-modal
                :visible="taskState.addOrEditVisible"
                :title="taskState.addOrEditTitle"
                centered
                :mask-closable="false"
                :keyboard="false"
                destroy-on-close
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
                width="1000px"
                @cancel="cancleMbTask"
            >
                <template #footer>
                    <a-button type="primary" @click="cancleMbTask"> 取消</a-button>
                    <a-button
                        type="primary"
                        v-if="taskState.current == 1"
                        @click="getTask"
                        :loading="taskState.nextLoading"
                    >
                        下一步</a-button
                    >
                    <a-button type="primary" v-if="taskState.current == 2" @click="taskState.current = 1">
                        上一步</a-button
                    >
                    <a-button
                        type="primary"
                        @click="confirmMbTask"
                        v-if="taskState.current == 2"
                        :loading="taskState.okLoading"
                    >
                        确定</a-button
                    >
                </template>
                <div class="form-model">
                    <a-form :model="taskState.modalForm" ref="taskFormRef" :rules="rules">
                        <a-row v-if="taskState.current == 1">
                            <a-col :span="24">
                                <a-form-item label="用户故事名称" name="storyId">
                                    <a-select
                                        :placeholder="selectHolder"
                                        v-model:value="taskState.modalForm.storyId"
                                        showSearch
                                        :options="taskState.storyList"
                                        :field-names="{ label: 'label', value: 'value' }"
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                        @focus="getStory"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="功能简称" name="functionAbbreviation">
                                    <a-input
                                        :placeholder="inputHolder"
                                        v-model:value="taskState.modalForm.functionAbbreviation"
                                        maxlength="10"
                                        show-count
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="SOP任务" name="templateTaskId">
                                    <a-tree-select
                                        v-model:value="taskState.modalForm.templateTaskId"
                                        show-search
                                        multiple
                                        treeCheckable
                                        style="width: 100%"
                                        placeholder="请选择"
                                        allow-clear
                                        treeDefaultExpandAll
                                        :tree-data="taskState.treeData"
                                        :fieldNames="{
                                            children: 'children',
                                            label: 'taskName',
                                            value: 'taskId',
                                            key: 'taskId'
                                        }"
                                        :filterTreeNode="
                                            (inputValue, treeNode) => {
                                                return (
                                                    treeNode.taskName.toLowerCase().indexOf(inputValue.toLowerCase()) >=
                                                    0
                                                )
                                            }
                                        "
                                        :max-tag-count="7"
                                        @focus="getTreeData"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>
                        <div v-else>
                            <div v-for="(item, index) in taskState.modalForm.taskList" :key="index" class="form-item">
                                <div class="form-content">
                                    <a-row class="one-line">
                                        <a-col :span="24">
                                            <a-form-item
                                                label="任务名称"
                                                :name="['taskList', index, 'taskName']"
                                                :rules="[
                                                    {
                                                        required: true,
                                                        message: '请输入任务名称!'
                                                    },
                                                    {
                                                        validator: () => {
                                                            if (taskState.modalForm.taskList[index].taskName) {
                                                                if (
                                                                    taskState.modalForm.taskList[index].taskName.trim()
                                                                ) {
                                                                    return PromiseProxy.resolve()
                                                                } else {
                                                                    return PromiseProxy.reject('请输入任务名称!')
                                                                }
                                                            } else {
                                                                return PromiseProxy.resolve()
                                                            }
                                                        }
                                                    }
                                                ]"
                                            >
                                                <a-input
                                                    disabled
                                                    :placeholder="inputHolder"
                                                    v-model:value="taskState.modalForm.taskList[index].taskName"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>

                                    <a-row>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="计划起止时间"
                                                :name="['taskList', index, 'allTime']"
                                                :rules="{ required: true, message: '请选择计划起止时间!' }"
                                            >
                                                <a-range-picker
                                                    style="width: 100%"
                                                    v-model:value="taskState.modalForm.taskList[index].allTime"
                                                    valueFormat="YYYY-MM-DD"
                                                    @change="getCurrentTaskParticipantList('modalForm', index)"
                                                />
                                            </a-form-item>
                                        </a-col>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="任务负责人"
                                                :name="['taskList', index, 'taskOwner']"
                                                :rules="{ required: true, message: '请选择任务负责人!' }"
                                            >
                                                <a-select
                                                    :placeholder="selectHolder"
                                                    v-model:value="taskState.modalForm.taskList[index].taskOwner"
                                                    showSearch
                                                    :options="peopleList"
                                                    :field-names="{ label: 'label', value: 'value' }"
                                                    :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                                                    @change="getCurrentTaskParticipantList('modalForm', index)"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="审核员"
                                                :name="['taskList', index, 'assessorName']"
                                                :rules="{ required: false, message: '请选择审核员!' }"
                                            >
                                                <a-select
                                                    :placeholder="selectHolder"
                                                    v-model:value="taskState.modalForm.taskList[index].assessorName"
                                                    showSearch
                                                    :options="peopleList"
                                                    :field-names="{ label: 'label', value: 'value' }"
                                                    :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                                                />
                                            </a-form-item>
                                        </a-col>
                                        <a-col :span="12">
                                            <a-form-item label="优先级">
                                                <a-select
                                                    :options="[
                                                        {
                                                            label: 'P0',
                                                            value: 'P0'
                                                        },
                                                        {
                                                            label: 'P1',
                                                            value: 'P1'
                                                        },
                                                        {
                                                            label: 'P2',
                                                            value: 'P2'
                                                        },
                                                        {
                                                            label: 'P3',
                                                            value: 'P3'
                                                        }
                                                    ]"
                                                    v-model:value="taskState.modalForm.taskList[index].priority"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row class="one-line">
                                        <a-col :span="24">
                                            <a-form-item
                                                label="任务执行人"
                                                :name="['taskList', index, 'taskParticipantList']"
                                                :rules="{ required: true, message: '请选择任务参与人!' }"
                                            >
                                                <a-select
                                                    :placeholder="selectHolder"
                                                    v-model:value="
                                                        taskState.modalForm.taskList[index].taskParticipantList
                                                    "
                                                    @change="getCurrentTaskParticipantList('modalForm', index)"
                                                    showSearch
                                                    mode="multiple"
                                                    :options="peopleList"
                                                    :field-names="{ label: 'label', value: 'value' }"
                                                    :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row>
                                        <a-col v-if="taskPeopleList.length > 0">
                                            <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                                                <a
                                                    href="javascript:;"
                                                    v-for="(item, num) in taskPeopleList"
                                                    @click="handlerAddPtMbPeopleTask(item.value, index)"
                                                    ><span style="margin: 0 5px">{{ item.value }}</span></a
                                                >
                                            </div>
                                        </a-col>
                                    </a-row>
                                    <a-row class="one-line">
                                        <a-col :span="24">
                                            <a-form-item
                                                label="预计投入工时"
                                                :name="['taskList', index, 'workingHours']"
                                                :rules="[
                                                    { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                                    {
                                                        pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                        message: '请输入大于0的数字(支持0.5的倍数)',
                                                        trigger: 'blur'
                                                    }
                                                ]"
                                            >
                                                <a-input
                                                    placeholder="请输入工时(支持0.5的数字)"
                                                    v-model:value="taskState.modalForm.taskList[index].workingHours"
                                                    :min="0"
                                                    type="number"
                                                    suffix="小时"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                </div>
                            </div>
                        </div>
                    </a-form>
                </div>
            </a-modal>
            <!--            新建sop任务-->
            <!--            新建问题-->
            <a-modal
                :visible="taskState.addOrEditQuestionVisible"
                :title="taskState.addOrEditQuestionTitle"
                centered
                destroy-on-close
                :mask-closable="false"
                :keyboard="false"
                @cancel="resetQuestion"
                @ok="questionSubmit"
                width="1000px"
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
                :ok-button-props="{ loading: taskState.questionLoading }"
            >
                <a-form :model="taskState.questionForm" ref="questionFormRef">
                    <div class="question-form">
                        <a-row>
                            <a-col :span="24">
                                <a-form-item
                                    label="用户故事"
                                    name="storyId"
                                    :rules="{ required: true, message: '请选择用户故事!' }"
                                >
                                    <a-select
                                        disabled
                                        :placeholder="selectHolder"
                                        v-model:value="taskState.questionForm.storyId"
                                        showSearch
                                        :options="taskState.storyList"
                                        :field-names="{ label: 'label', value: 'value' }"
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                        allow-clear
                                        @focus="getStory"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="任务">
                                    <!--                                    treeCheckable-->
                                    <a-tree-select
                                        disabled
                                        v-model:value="taskState.questionForm.parentId"
                                        show-search
                                        style="width: 100%"
                                        placeholder="请选择"
                                        allow-clear
                                        treeDefaultExpandAll
                                        :tree-data="taskState.questionTaskList"
                                        :fieldNames="{
                                            children: 'children',
                                            label: 'taskName',
                                            value: 'taskId',
                                            key: 'taskId'
                                        }"
                                        :filterTreeNode="
                                            (inputValue, treeNode) => {
                                                return (
                                                    treeNode.taskName.toLowerCase().indexOf(inputValue.toLowerCase()) >=
                                                    0
                                                )
                                            }
                                        "
                                        @focus="getQuestionTask"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item
                                    label="问题名称"
                                    name="taskName"
                                    :rules="{ required: true, message: '请输入问题名称!' }"
                                >
                                    <a-input
                                        v-model:value="taskState.questionForm.taskName"
                                        :placeholder="inputHolder"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item
                                    label="问题描述"
                                    :rules="[{ required: true, message: '请输入问题描述', trigger: 'blur' }]"
                                    name="description"
                                >
                                    <QuillEditor
                                        v-model:content="taskState.questionForm.description"
                                        ref="taskQuillEditor"
                                        :options="editorOption"
                                        class="quill-editor"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="问题类型"
                                    :rules="[{ required: true, message: '请选择问题类型', trigger: 'blur' }]"
                                    name="problemType"
                                >
                                    <a-select
                                        :placeholder="selectHolder"
                                        v-model:value="taskState.questionForm.problemType"
                                        :options="taskState.problemList"
                                        :field-names="{ label: 'label', value: 'label' }"
                                        :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="优先级"
                                    :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]"
                                    name="priority"
                                >
                                    <a-select
                                        :options="[
                                            {
                                                label: 'P0',
                                                value: 'P0'
                                            },
                                            {
                                                label: 'P1',
                                                value: 'P1'
                                            },
                                            {
                                                label: 'P2',
                                                value: 'P2'
                                            },
                                            {
                                                label: 'P3',
                                                value: 'P3'
                                            }
                                        ]"
                                        v-model:value="taskState.questionForm.priority"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="版本">
                                    <a-input
                                        v-model:value="taskState.questionForm.version"
                                        :placeholder="inputHolder"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="计划开始时间"
                                    :rules="[{ required: false, message: '请选择计划开始时间', trigger: 'blur' }]"
                                    name="startTime"
                                >
                                    <a-date-picker
                                        style="width: 100%"
                                        v-model:value="taskState.questionForm.startTime"
                                        value-format="YYYY-MM-DD"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="计划完成时间"
                                    :rules="[{ required: false, message: '请选择计划完成时间', trigger: 'blur' }]"
                                    name="endTime"
                                >
                                    <a-date-picker
                                        style="width: 100%"
                                        v-model:value="taskState.questionForm.endTime"
                                        value-format="YYYY-MM-DD"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="解决人"
                                    :rules="[{ required: true, message: '请选择解决人', trigger: 'blur' }]"
                                    name="taskParticipant"
                                >
                                    <a-select
                                        :placeholder="selectHolder"
                                        :options="groupList"
                                        :allowClear="true"
                                        :dropdownMatchSelectWidth="true"
                                        :showSearch="true"
                                        :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                        :max-tag-count="1"
                                        :showArrow="true"
                                        v-model:value="taskState.questionForm.taskParticipant"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>
                    </div>
                </a-form>
            </a-modal>
            <!--            新建问题-->
            <!--          任务相关弹窗==================================================================================-->
            <!--          显示设置-->
            <a-modal
                :visible="showState.settingVisible"
                title="显示设置"
                centered
                width="700px"
                @ok="confirmSetting"
                @cancel="showState.settingVisible = false"
                :ok-button-props="{
                    loading: showState.settingLoading
                }"
                :mask-closable="false"
                :keyboard="false"
            >
                <a-checkbox v-model:checked="showState.storyAllCheck" @change="storyAllChange">用户故事</a-checkbox>
                <a-checkbox-group
                    @change="handleStoryCheckChange"
                    v-model:value="showState.storyCheckList"
                    style="width: 100%"
                >
                    <a-row>
                        <a-col
                            :span="6"
                            v-for="(story, index) in columns.filter(
                                c => !['操作', '用户故事名称', '版本号'].includes(c.title)
                            )"
                        >
                            <a-checkbox :value="story.title">{{ story.title }}</a-checkbox>
                        </a-col>
                    </a-row>
                </a-checkbox-group>
                <a-divider style="margin: 10px 0" />
                <a-checkbox v-model:checked="showState.taskAllCheck" @change="taskAllChange">任务</a-checkbox>
                <a-checkbox-group
                    @change="handleTaskCheckChange"
                    v-model:value="showState.taskCheckList"
                    style="width: 100%"
                >
                    <a-row>
                        <a-col
                            :span="6"
                            v-for="(task, index) in innerColumns.filter(c => !['操作', '任务名称'].includes(c.title))"
                        >
                            <a-checkbox :value="task.title">{{ task.title }}</a-checkbox>
                        </a-col>
                    </a-row>
                </a-checkbox-group>
            </a-modal>
            <!--          显示设置-->
            <!--            新建/编辑用户故事-->
            <a-modal
                :visible="milepostState.addOrEditVisible"
                :title="milepostState.addOrEditTitle"
                centered
                :mask-closable="false"
                :keyboard="false"
                destroy-on-close
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
                width="1000px"
                @cancel="cancelStory"
            >
                <template #footer>
                    <a-button type="primary" @click="storyCancleMbTask"> 取消</a-button>
                    <a-button
                        type="primary"
                        v-if="
                            milepostState.current == 1 &&
                            milepostState.modalForm.templateTaskId?.length > 0 &&
                            !currentStoryData.id
                        "
                        @click="getTaskStory"
                        :loading="milepostState.nextLoading"
                    >
                        下一步</a-button
                    >
                    <a-button type="primary" v-if="milepostState.current == 2" @click="milepostState.current = 1">
                        上一步</a-button
                    >
                    <a-button
                        type="primary"
                        @click="storyConfirmMbTask"
                        v-if="
                            milepostState.current == 2 ||
                            (milepostState.modalForm.templateTaskId?.length == 0 && milepostState.current == 1)
                        "
                        :loading="milepostState.okLoading"
                    >
                        确定</a-button
                    >
                </template>
                <div class="form-model">
                    <a-form :model="milepostState.modalForm" ref="storyFormRef" :rules="storyRules">
                        <a-row v-if="milepostState.current == 1">
                            <a-col :span="12">
                                <a-form-item label="月份">
                                    <a-date-picker
                                        v-model:value="milepostState.modalForm.monthlyGoalTargetMonth"
                                        value-format="YYYY-MM"
                                        picker="month"
                                        style="width: 100%"
                                        @change="milepostState.modalForm.projectMonthlyGoalManagementId = undefined"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="月度子目标">
                                    <a-select
                                        :options="milepostState.targetList"
                                        v-model:value="milepostState.modalForm.projectMonthlyGoalManagementId"
                                        show-search
                                        :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                        allow-clear
                                        @focus="getTarget"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="用户故事名称" name="storyName">
                                    <a-input
                                        v-model:value="milepostState.modalForm.storyName"
                                        :placeholder="inputHolder"
                                        maxlength="100"
                                        show-count
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="版本号" name="iterationVersionId">
                                    <a-select
                                        v-model:value="milepostState.modalForm.iterationVersionId"
                                        placeholder="请选择"
                                        allowClear
                                        :options="state.versionList"
                                        show-search
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="负责人" name="ownerList">
                                    <a-select
                                        v-model:value="milepostState.modalForm.ownerList"
                                        placeholder="请选择"
                                        allowClear
                                        mode="multiple"
                                        :options="peopleList"
                                        show-search
                                        :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item label="计划起止时间">
                                    <a-range-picker
                                        style="width: 100%"
                                        v-model:value="milepostState.modalForm.timeRangeList"
                                        valueFormat="YYYY-MM-DD"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="12">
                                <a-form-item
                                    label="优先级"
                                    name="priority"
                                    :rules="[{ required: true, msssage: '请选择优先级', trigger: 'blur' }]"
                                >
                                    <a-select
                                        :options="[
                                            {
                                                label: 'P0',
                                                value: 'P0'
                                            },
                                            {
                                                label: 'P1',
                                                value: 'P1'
                                            },
                                            {
                                                label: 'P2',
                                                value: 'P2'
                                            },
                                            {
                                                label: 'P3',
                                                value: 'P3'
                                            }
                                        ]"
                                        v-model:value="milepostState.modalForm.priority"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="描述">
                                    <QuillEditor
                                        v-model:content="milepostState.modalForm.description"
                                        ref="storyQuillEditor"
                                        :options="editorOption"
                                        class="quill-editor"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24">
                                <a-form-item label="标签" name="labels">
                                    <a-input
                                        v-model:value="milepostState.modalForm.labels"
                                        show-count
                                        :placeholder="inputHolder"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24" v-if="!currentStoryData.id">
                                <a-form-item
                                    label="功能简称"
                                    name="functionAbbreviation"
                                    :rules="[
                                        {
                                            required: false,
                                            message: '请输入功能简称',
                                            trigger: 'blur'
                                        }
                                    ]"
                                >
                                    <a-input
                                        :placeholder="inputHolder"
                                        v-model:value="milepostState.modalForm.functionAbbreviation"
                                        maxlength="10"
                                        show-count
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="24" v-if="!currentStoryData.id">
                                <a-form-item label="SOP任务">
                                    <a-tree-select
                                        v-model:value="milepostState.modalForm.templateTaskId"
                                        show-search
                                        multiple
                                        treeCheckable
                                        style="width: 100%"
                                        placeholder="请选择"
                                        allow-clear
                                        treeDefaultExpandAll
                                        :tree-data="milepostState.treeData"
                                        :fieldNames="{
                                            children: 'children',
                                            label: 'taskName',
                                            value: 'taskId',
                                            key: 'taskId'
                                        }"
                                        :filterTreeNode="
                                            (inputValue, treeNode) => {
                                                return (
                                                    treeNode.taskName.toLowerCase().indexOf(inputValue.toLowerCase()) >=
                                                    0
                                                )
                                            }
                                        "
                                        :max-tag-count="7"
                                        @focus="getTreeData"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>
                        <div v-else>
                            <div
                                v-for="(item, index) in milepostState.modalForm.taskList"
                                :key="index"
                                class="form-item"
                            >
                                <div class="form-content">
                                    <a-row class="one-line">
                                        <a-col :span="24">
                                            <a-form-item
                                                label="任务名称"
                                                :name="['taskList', index, 'taskName']"
                                                :rules="[
                                                    {
                                                        required: true,
                                                        message: '请输入任务名称!'
                                                    },
                                                    {
                                                        validator: () => {
                                                            if (milepostState.modalForm.taskList[index].taskName) {
                                                                if (
                                                                    milepostState.modalForm.taskList[
                                                                        index
                                                                    ].taskName.trim()
                                                                ) {
                                                                    return PromiseProxy.resolve()
                                                                } else {
                                                                    return PromiseProxy.reject('请输入任务名称!')
                                                                }
                                                            } else {
                                                                return PromiseProxy.resolve()
                                                            }
                                                        }
                                                    }
                                                ]"
                                            >
                                                <a-input
                                                    disabled
                                                    :placeholder="inputHolder"
                                                    v-model:value="milepostState.modalForm.taskList[index].taskName"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>

                                    <a-row>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="计划起止时间"
                                                :name="['taskList', index, 'allTime']"
                                                :rules="{ required: true, message: '请选择计划起止时间!' }"
                                            >
                                                <a-range-picker
                                                    style="width: 100%"
                                                    v-model:value="milepostState.modalForm.taskList[index].allTime"
                                                    valueFormat="YYYY-MM-DD"
                                                    @change="getStoryTaskParticipantList('modalForm', index)"
                                                />
                                            </a-form-item>
                                        </a-col>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="任务负责人"
                                                :name="['taskList', index, 'taskOwner']"
                                                :rules="{ required: true, message: '请选择任务负责人!' }"
                                            >
                                                <a-select
                                                    :placeholder="selectHolder"
                                                    v-model:value="milepostState.modalForm.taskList[index].taskOwner"
                                                    showSearch
                                                    :options="peopleList"
                                                    :field-names="{ label: 'label', value: 'value' }"
                                                    :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="审核员"
                                                :name="['taskList', index, 'assessorName']"
                                                :rules="{ required: true, message: '请选择审核员!' }"
                                            >
                                                <a-select
                                                    :placeholder="selectHolder"
                                                    v-model:value="milepostState.modalForm.taskList[index].assessorName"
                                                    showSearch
                                                    :options="peopleList"
                                                    :field-names="{ label: 'label', value: 'value' }"
                                                    :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                                                />
                                            </a-form-item>
                                        </a-col>
                                        <a-col :span="12">
                                            <a-form-item
                                                label="优先级"
                                                :name="['taskList', index, 'priority']"
                                                :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]"
                                            >
                                                <a-select
                                                    :options="[
                                                        {
                                                            label: 'P0',
                                                            value: 'P0'
                                                        },
                                                        {
                                                            label: 'P1',
                                                            value: 'P1'
                                                        },
                                                        {
                                                            label: 'P2',
                                                            value: 'P2'
                                                        },
                                                        {
                                                            label: 'P3',
                                                            value: 'P3'
                                                        }
                                                    ]"
                                                    v-model:value="milepostState.modalForm.taskList[index].priority"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row class="one-line">
                                        <a-col :span="24">
                                            <a-form-item
                                                label="任务执行人"
                                                :name="['taskList', index, 'taskParticipantList']"
                                                :rules="{ required: true, message: '请选择任务参与人!' }"
                                            >
                                                <a-select
                                                    :placeholder="selectHolder"
                                                    v-model:value="
                                                        milepostState.modalForm.taskList[index].taskParticipantList
                                                    "
                                                    showSearch
                                                    mode="multiple"
                                                    :options="peopleList"
                                                    :field-names="{ label: 'label', value: 'value' }"
                                                    :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                                                    @change="getStoryTaskParticipantList('modalForm', index)"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row>
                                        <a-col v-if="taskPeopleList.length > 0">
                                            <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                                                <a
                                                    href="javascript:;"
                                                    v-for="(item, num) in taskPeopleList"
                                                    @click="handlerAddPtMbPeople(item.value, index)"
                                                    ><span style="margin: 0 5px">{{ item.value }}</span></a
                                                >
                                            </div>
                                        </a-col>
                                    </a-row>
                                    <a-row>
                                        <a-col :span="24">
                                            <a-form-item
                                                label="预计投入工时"
                                                :name="['taskList', index, 'workingHours']"
                                                :rules="[
                                                    { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                                    {
                                                        pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                        message: '请输入大于0的数字(支持0.5的倍数)',
                                                        trigger: 'blur'
                                                    }
                                                ]"
                                            >
                                                <a-input
                                                    placeholder="请输入工时(支持0.5的数字)"
                                                    v-model:value="milepostState.modalForm.taskList[index].workingHours"
                                                    :min="0"
                                                    type="number"
                                                    suffix="小时"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                    <a-row class="one-line">
                                        <a-col :span="24">
                                            <a-form-item label="备注">
                                                <a-textarea
                                                    v-model:value="milepostState.modalForm.taskList[index].remark"
                                                />
                                            </a-form-item>
                                        </a-col>
                                    </a-row>
                                </div>
                            </div>
                        </div>
                    </a-form>
                </div>
            </a-modal>
            <!--            新建/编辑用户故事-->
            <!--            查看问题-->
            <a-modal
                :visible="showMsgState.visible"
                title="用户故事描述"
                :footer="null"
                centered
                @cancel="cancelShowMsg"
                width="1000px"
                :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
            >
                <div class="item-content" v-html="getHtmlContent(showMsgState.msg)"> </div>
            </a-modal>
            <!--            查看问题-->
            <div class="body" :style="{ padding: hasJump ? '16px' : '0' }">
                <div class="top-search" :style="{ paddingTop: hasJump ? '16px' : '0' }">
                    <!-- 第一行筛选条件 -->
                    <a-row :gutter="16">
                        <a-col :span="10" class="story-name-select" style="min-width: 0">
                            <a-form-item label="用户故事">
                                <a-select
                                    :placeholder="selectHolder"
                                    v-model:value="state.filter.storyId"
                                    showSearch
                                    :options="taskState.storyList"
                                    :field-names="{ label: 'label', value: 'value' }"
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    @focus="getStory"
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="8">
                            <a-form-item label="版本号">
                                <a-select
                                    v-model:value="state.filter.iterationVersionId"
                                    placeholder="请选择"
                                    allowClear
                                    :options="state.filterVersionList"
                                    show-search
                                    :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                />
                            </a-form-item>
                        </a-col>
                        <a-col :span="6">
                            <a-form-item label="任务人员">
                                <a-select
                                    :placeholder="selectHolder"
                                    :options="peopleList"
                                    :allowClear="true"
                                    :dropdownMatchSelectWidth="true"
                                    :showSearch="true"
                                    :filterOption="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                                    :max-tag-count="1"
                                    :showArrow="true"
                                    v-model:value="state.filter.userName"
                                />
                            </a-form-item>
                        </a-col>
                    </a-row>
                    <template v-if="expanded">
                        <!-- 第二行 -->
                        <a-row :gutter="16" class="story-name-select">
                            <a-col :span="5" class="story-name-select">
                                <a-form-item label="标签">
                                    <a-select
                                        :placeholder="selectHolder"
                                        allow-clear
                                        v-model:value="state.filter.storyLabels"
                                        :options="milepostState.labelList"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="5">
                                <a-form-item label="用户故事状态">
                                    <a-select
                                        :placeholder="selectHolder"
                                        allow-clear
                                        v-model:value="state.filter.storyStatus"
                                        :options="milepostState.statusList"
                                        :field-names="{
                                            label: 'label',
                                            value: 'label'
                                        }"
                                        :showSearch="true"
                                        :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="8">
                                <a-form-item label="故事计划完成">
                                    <a-range-picker
                                        v-model:value="state.filter.storyEndTimeList"
                                        value-format="YYYY-MM-DD"
                                        style="width: 100%"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="6">
                                <a-form-item label="用户故事排序">
                                    <a-select
                                        v-model:value="state.filter.storyDirectionField"
                                        placeholder="请选择"
                                        allowClear
                                        :options="milepostState.sortList"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>

                        <!-- 折叠区域 -->

                        <a-row :gutter="16">
                            <a-col :span="5">
                                <a-form-item label="任务状态">
                                    <a-select
                                        v-model:value="state.filter.taskStatus"
                                        placeholder="请选择"
                                        allowClear
                                        :options="state.taskOptions"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="5">
                                <a-form-item label="任务类型">
                                    <a-select
                                        v-model:value="state.filter.taskType"
                                        placeholder="请选择"
                                        allowClear
                                        :options="[
                                            { label: 'SOP任务', value: 'SOP任务' },

                                            { label: '子任务', value: '子任务' },
                                            { label: '问题', value: '问题' }
                                        ]"
                                    />
                                </a-form-item>
                            </a-col>

                            <a-col :span="8">
                                <a-form-item label="任务计划完成">
                                    <a-range-picker
                                        v-model:value="state.filter.endTimeList"
                                        style="width: 100%"
                                        value-format="YYYY-MM-DD"
                                    />
                                </a-form-item>
                            </a-col>
                            <a-col :span="6">
                                <a-form-item label="任务排序">
                                    <a-select
                                        v-model:value="state.filter.directionField"
                                        placeholder="请选择"
                                        allowClear
                                        :options="taskState.sortList"
                                    />
                                </a-form-item>
                            </a-col>
                        </a-row>
                    </template>

                    <!-- 操作按钮 -->
                    <div class="table-top">
                        <div class="tip-msg">用户故事列表</div>

                        <div class="right-btn">
                            <a-button @click="handleAdd" v-permission="'3000001021_vid_nvuzhmai4w'" type="primary"
                                >新建用户故事</a-button
                            >
                            <a-button v-permission="'50001252_vid_wcf3s76l4c'" @click="handleAddSopTask" type="primary"
                                >新建SOP任务</a-button
                            >
                            <a-button @click="handleAddSonTask" v-permission="'50001252_vid_9rui2q7sid'" type="primary"
                                >新建子任务</a-button
                            >
                            <a-button
                                v-permission="'50001252_vid_azzpjat1q3'"
                                @click="handlerShowCheck"
                                type="primary"
                                :loading="keyNoteLoading"
                                >{{ state.showCheck ? '保存' : '关键路径任务' }}</a-button
                            >
                            <!--                            <a-button @click="handleExpendAll" type="primary">{{-->
                            <!--                                state.expendAll ? '全部收起' : '全部展开'-->
                            <!--                            }}</a-button>-->
                            <a-button type="primary" v-permission="'50001252_vid_4q8gq5nr48'" @click="showSetting"
                                >显示设置</a-button
                            >
                            <a-button type="primary" @click="getData">查询</a-button>
                            <a-button @click="reset" type="primary" ghost>重置</a-button>

                            <a-button
                                type="link"
                                size="small"
                                style="padding: 0"
                                @click="
                                    () => {
                                        expanded = !expanded
                                        if (expanded) {
                                            headerOffset = 230
                                            calcTableHeight()
                                        } else {
                                            headerOffset = 150
                                            calcTableHeight()
                                        }
                                    }
                                "
                            >
                                <template #icon>
                                    <DoubleRightOutlined
                                        :style="{
                                            transform: expanded ? 'rotate(270deg)' : 'rotate(90deg)'
                                        }"
                                    />
                                </template>
                                {{ expanded ? '收起' : '展开' }}
                            </a-button>
                        </div>
                    </div>
                </div>
                <div class="table-box-story">
                    <div class="expend-btn" @click="toggleExpandAll">
                        <a-spin :spinning="expendSping">
                            <PlusSquareOutlined v-if="!isAllExpanded" title="展开全部" />
                            <MinusSquareOutlined v-if="isAllExpanded" title="收起全部" />
                        </a-spin>
                    </div>
                    <a-table
                        :columns="displayStoryColumns"
                        :data-source="state.dataSource"
                        bordered
                        :loading="state.tableLoading"
                        :scroll="{ x: '1200px', y: state.tableHeight }"
                        :pagination="false"
                        row-key="id"
                        size="small"
                        :rowSelection="storyRowSelection"
                        @resizeColumn="handleResizeStoryColumn"
                        :expandedRowKeys="state.expandedRowKeys"
                        @expandedRowsChange="keys => (state.expandedRowKeys = keys)"
                    >
                        <template #bodyCell="{ column, record }">
                            <template v-if="column.dataIndex === 'storyName'">
                                <div class="task-name-body">
                                    <div class="task-title">
                                        <div title="用户故事" class="type-tag story-bg" style="color: #3875ff"></div>
                                        <div
                                            v-if="record.keynote === '是'"
                                            class="critical-path"
                                            title="关键路径"
                                        ></div>

                                        <!-- 需求编号：只在存在时显示；用 wrapper 保证 tooltip 有单一根元素 -->
                                        <template v-if="hasNumberList(record)">
                                            <a-tooltip :title="formatAllCodes(record.numberList)" placement="top">
                                                <span class="tags-wrapper">
                                                    <a-tag color="purple" class="mr-1">{{
                                                        formatFirstCode(record.numberList)
                                                    }}</a-tag>
                                                </span>
                                            </a-tooltip>
                                        </template>

                                        <!-- 标签展示：只有在有标签数组时显示；tooltip 内部使用单一 wrapper 元素 -->
                                        <template v-if="hasLabels(record)">
                                            <a-tooltip :title="formatAllLabels(record.labels)" placement="top">
                                                <span class="tags-wrapper">
                                                    <!-- v-for 放在 a-tag 上，key 使用 label+index 保证稳定 -->
                                                    <a-tag
                                                        v-for="(label, idx) in formatShowLabels(record.labels)"
                                                        :key="`${label}::${idx}`"
                                                        color="blue"
                                                        class="mr-1"
                                                    >
                                                        {{ label }}
                                                    </a-tag>
                                                </span>
                                            </a-tooltip>
                                        </template>

                                        <div
                                            class="story-name-color"
                                            :title="record.storyName"
                                            @click="showDescription(record, '故事')"
                                        >
                                            {{ record.storyName }}
                                        </div>
                                    </div>
                                </div>
                            </template>
                            <template v-if="column.dataIndex === 'storyStatus'">
                                <div
                                    title="用户故事状态"
                                    class="status-tag story-status"
                                    :style="{
                                        backgroundColor: getStatusColor(record.storyStatus)
                                    }"
                                    >{{ record.storyStatus }}</div
                                >
                            </template>
                            <template v-if="column.dataIndex === 'progress'">
                                <a-tooltip>
                                    <template #title>
                                        <div>
                                            <div>任务总数{{ record.taskNumber }}个</div>
                                            <div class="flex-color">
                                                <div class="no-start"></div>
                                                <div>未开始任务数{{ record.noStartTaskNumber }}个</div>
                                            </div>
                                            <div class="flex-color">
                                                <div class="running"></div>
                                                <div>进行中任务数{{ record.runningTaskNumber }}个</div>
                                            </div>
                                            <div class="flex-color">
                                                <div class="finish"></div>
                                                <div>已完成任务数{{ record.finishTaskNumber }}个</div>
                                            </div>
                                        </div>
                                    </template>
                                    <div style="display: flex; gap: 8px">
                                        <a-progress
                                            style="width: 150px"
                                            :percent="totalPercent(record)"
                                            :success="{ percent: finishPercent(record), strokeColor: '52c41a' }"
                                            :show-info="false"
                                            trailColor="#d9d9d9"
                                            strokeColor="#3875ff"
                                        />
                                        <div
                                            >{{
                                                formatPercentage(
                                                    record.taskNumber
                                                        ? (record.finishTaskNumber / record.taskNumber) * 100
                                                        : 0
                                                )
                                            }}%</div
                                        >
                                    </div>
                                </a-tooltip>
                            </template>
                            <template v-if="column.dataIndex === 'priority'">
                                <div
                                    class="priority-tag"
                                    title="优先级"
                                    :style="{ backgroundColor: getBgc(record.priority) }"
                                    >{{ record.priority || 'NO' }}</div
                                >
                            </template>
                            <template v-if="column.dataIndex === 'fatherOperation'">
                                <a-space :size="0">
                                    <a-button
                                        size="small"
                                        type="link"
                                        v-permission="'3000001021_vid_b9yp1prrhr'"
                                        @click="showQuestionMsg(record.description)"
                                        >描述</a-button
                                    >

                                    <a-button
                                        v-permission="'3000001021_vid_apf0s6w3ri'"
                                        size="small"
                                        type="link"
                                        @click="handleEditStory(record)"
                                        >编辑</a-button
                                    >

                                    <a-dropdown>
                                        <a-button size="small" type="link">
                                            更多
                                            <EllipsisOutlined style="rotate: 90deg; font-size: 14px; margin: 0" />
                                        </a-button>
                                        <template #overlay>
                                            <a-menu>
                                                <a-menu-item v-permission="'3000001021_vid_sabdi0uugq'">
                                                    <a-popconfirm
                                                        title="是否确认删除？由需求池转化的用户故事删除后需求状态将变更为未转化?"
                                                        ok-text="确定"
                                                        placement="left"
                                                        cancel-text="取消"
                                                        @confirm="confirmDelete(record.id)"
                                                        @cancel="cancel"
                                                    >
                                                        <a-button size="small" type="link">删除</a-button>
                                                    </a-popconfirm>
                                                </a-menu-item>
                                                <a-menu-item v-permission="'50001252_vid_efgx6i1a59'">
                                                    <a-button size="small" type="link" @click="handlerShowNotes(record)"
                                                        >备注</a-button
                                                    >
                                                </a-menu-item>
                                                <a-menu-item v-permission="'50001252_vid_xznx32lnx9'">
                                                    <a-button size="small" @click="showChangeLog(record)" type="link"
                                                        >变更记录</a-button
                                                    >
                                                </a-menu-item>
                                                <a-menu-item v-permission="'50001252_vid_ewy34rdv53'">
                                                    <a-button size="small" type="link" @click="showTransfer(record)"
                                                        >转移</a-button
                                                    >
                                                </a-menu-item>
                                                <a-menu-item v-permission="'50001252_vid_kb3wilkru7'">
                                                    <a-button size="small" type="link" @click="showCorrelation(record)"
                                                        >关联需求</a-button
                                                    >
                                                </a-menu-item>
                                            </a-menu>
                                        </template>
                                    </a-dropdown>
                                </a-space>
                            </template>
                        </template>
                        <template #expandedRowRender="{ record }">
                            <a-table
                                :columns="displayTaskColumns"
                                :data-source="record.taskChildrenList"
                                :pagination="false"
                                bordered
                                class="table-box-task"
                                :scroll="{ x: '1800px' }"
                                row-key="taskId"
                                :rowSelection="
                                    state.showCheck
                                        ? {
                                              selectedRowKeys: state.selectedTaskKeys[record.id] || [],
                                              onChange: keys => {
                                                  state.selectedTaskKeys[record.id] = keys
                                              },
                                              getCheckboxProps: taskRecord => ({
                                                  disabled: taskRecord.taskType === '问题'
                                              })
                                          }
                                        : null
                                "
                                @resizeColumn="handleResizeTaskColumn"
                            >
                                <template #headerCell="{ column, title }">
                                    <template v-if="title === '操作'">
                                        <div style="display: flex; align-items: center; justify-content: center">{{
                                            title
                                        }}</div>
                                    </template>
                                </template>
                                <template #bodyCell="{ column, record }">
                                    <template v-if="column.dataIndex === 'priority'">
                                        <div
                                            class="priority-tag"
                                            title="优先级"
                                            :style="{ backgroundColor: getBgc(record.priority) }"
                                            >{{ record.priority || 'NO' }}</div
                                        >
                                    </template>
                                    <!--                                      任务名称-->
                                    <template v-if="column.dataIndex === 'taskName'">
                                        <div class="task-name-body">
                                            <div class="task-title">
                                                <div
                                                    :title="record.taskType"
                                                    class="type-tag"
                                                    :class="[classMap[record.taskType] || '']"
                                                >
                                                </div>
                                                <div
                                                    v-if="record.keynote === '是'"
                                                    class="critical-path"
                                                    title="关键路径"
                                                ></div>
                                                <div>
                                                    <span
                                                        class="name-color"
                                                        @click="showDescription(record, '任务')"
                                                        :title="record.taskName"
                                                    >
                                                        {{ record.taskName }}</span
                                                    >

                                                    <span class="story-task-name" v-if="record.taskType !== '问题'"
                                                        >-{{ record.storyName }}</span
                                                    >
                                                </div>
                                            </div>
                                        </div>
                                    </template>
                                    <!--                                      任务状态-->
                                    <template v-if="column.dataIndex === 'taskStatus'">
                                        <div class="edit-approve">
                                            <div
                                                class="status-tag"
                                                title="任务状态"
                                                :style="{
                                                    backgroundColor: getStatusColor(record.taskStatus)
                                                }"
                                                >{{ record.taskStatus || '暂无' }}</div
                                            >
                                            <div
                                                title="审批详情-变更"
                                                style="padding: 3px; border-left: 1px solid #fff; background: #fff"
                                                @click.stop="
                                                    getTaskStatus(
                                                        record.taskId,
                                                        0,
                                                        record.milepostId,
                                                        record.taskStatus,
                                                        record.taskType,
                                                        record
                                                    )
                                                "
                                            >
                                                <div class="can-edit"></div>
                                            </div>
                                        </div>
                                    </template>
                                    <!--                                      附件模板-->
                                    <template v-if="column.dataIndex === 'attachmentTemplateList'">
                                        <div
                                            v-if="
                                                record.attachmentTemplateList &&
                                                record.attachmentTemplateList.length > 0
                                            "
                                            class="item-content main-font under-line"
                                            @click="showMore(record.attachmentTemplateList)"
                                        >
                                            查看
                                        </div>
                                    </template>
                                    <!--                                      附件-->
                                    <template v-if="column.dataIndex === 'attachmentList'">
                                        <div
                                            v-if="record.attachmentList?.length > 0"
                                            class="item-content main-font under-line"
                                            @click="showMore(record.attachmentList)"
                                            >查看</div
                                        >
                                    </template>
                                    <template v-else-if="column.dataIndex === 'operation'">
                                        <a-space :size="0">
                                            <a-button
                                                size="small"
                                                type="link"
                                                ghost
                                                :loading="record.startLoading"
                                                v-if="!record.examPassTime"
                                                :disabled="openDisabledStory(record)"
                                                @click="handleOpen(record)"
                                            >
                                                开始
                                            </a-button>

                                            <a-button
                                                size="small"
                                                type="link"
                                                ghost
                                                v-if="record.examPassTime && !record.taskFinishTime"
                                                @click="beforeOkMb(record)"
                                                :disabled="disabledComplate(record)"
                                            >
                                                完成
                                            </a-button>
                                            <a-popconfirm
                                                title="确定恢复该任务?"
                                                ok-text="确定"
                                                cancel-text="取消"
                                                placement="left"
                                                @confirm="confirmRecoverTask(record)"
                                                @cancel="cancel"
                                                :disabled="disabledRestore(record)"
                                            >
                                                <a-button
                                                    size="small"
                                                    type="link"
                                                    ghost
                                                    v-if="record.taskFinishTime"
                                                    :disabled="disabledRestore(record)"
                                                >
                                                    恢复
                                                </a-button>
                                            </a-popconfirm>
                                            <a-button
                                                size="small"
                                                type="link"
                                                ghost
                                                @click="handleEditTask(record)"
                                                :disabled="disabledEditBtnStory(record.taskStatus)"
                                            >
                                                编辑
                                            </a-button>

                                            <a-dropdown>
                                                <template #overlay>
                                                    <a-menu @click="handleMenuClick">
                                                        <!-- 删除任务 -->
                                                        <a-menu-item
                                                            v-if="
                                                                record.taskType === 'SOP任务' ||
                                                                record.taskType === '子任务'
                                                            "
                                                            key="8"
                                                        >
                                                            <a-popconfirm
                                                                title="确定删除?"
                                                                ok-text="确定"
                                                                cancel-text="取消"
                                                                placement="left"
                                                                @confirm="confirmDeleteTask(record)"
                                                                @cancel="cancel"
                                                                :disabled="
                                                                    !(
                                                                        record.taskOwnerPermission ||
                                                                        record.createPermission
                                                                    )
                                                                "
                                                            >
                                                                <a-button
                                                                    size="small"
                                                                    type="link"
                                                                    ghost
                                                                    :disabled="
                                                                        !(
                                                                            record.taskOwnerPermission ||
                                                                            record.createPermission
                                                                        )
                                                                    "
                                                                >
                                                                    删除任务
                                                                </a-button>
                                                            </a-popconfirm>
                                                        </a-menu-item>

                                                        <!-- 删除问题 -->
                                                        <a-menu-item v-if="record.taskType === '问题'" key="8">
                                                            <a-popconfirm
                                                                title="确定删除?"
                                                                ok-text="确定"
                                                                placement="left"
                                                                cancel-text="取消"
                                                                @confirm="confirmDeleteQuestion(record)"
                                                                @cancel="cancel"
                                                                :disabled="!record.createPermission"
                                                            >
                                                                <a-button
                                                                    size="small"
                                                                    type="link"
                                                                    ghost
                                                                    :disabled="!record.createPermission"
                                                                >
                                                                    删除问题
                                                                </a-button>
                                                            </a-popconfirm>
                                                        </a-menu-item>

                                                        <!-- 描述 -->
                                                        <a-menu-item
                                                            v-if="record.taskType === '问题' && record.description"
                                                            key="3"
                                                            v-permission="'50001252_vid_v1eqodhtmg'"
                                                        >
                                                            <a-button
                                                                size="small"
                                                                type="link"
                                                                @click="showQuestionMsg(record.description)"
                                                            >
                                                                描述
                                                            </a-button>
                                                        </a-menu-item>

                                                        <!-- 流转 -->
                                                        <a-menu-item
                                                            v-if="
                                                                record.taskType === '问题' &&
                                                                record.taskStatus !== '完成' &&
                                                                record.taskStatus !== '延期完成'
                                                            "
                                                            key="4"
                                                        >
                                                            <a-button
                                                                size="small"
                                                                type="link"
                                                                ghost
                                                                :disabled="isCirculationDisabledStory(record)"
                                                                @click="showCirculation(record, '流转')"
                                                            >
                                                                流转
                                                            </a-button>
                                                        </a-menu-item>

                                                        <!-- +问题 -->
                                                        <a-menu-item
                                                            v-if="record.taskType !== '问题'"
                                                            key="5"
                                                            v-permission="'50001252_vid_6fu420wh3s'"
                                                        >
                                                            <a-button
                                                                size="small"
                                                                type="link"
                                                                ghost
                                                                :disabled="addQuestionDisabled(record)"
                                                                @click="handleAddQuestion(record)"
                                                            >
                                                                +问题
                                                            </a-button>
                                                        </a-menu-item>

                                                        <!--                                                        &lt;!&ndash; 提测 &ndash;&gt;-->
                                                        <!--                                                        <a-menu-item-->
                                                        <!--                                                            v-if="-->
                                                        <!--                                                                record.taskType !== '问题' &&-->
                                                        <!--                                                                record.examPassTime &&-->
                                                        <!--                                                                record.taskStatus !== '完成' &&-->
                                                        <!--                                                                record.taskStatus !== '测试中' &&-->
                                                        <!--                                                                record.taskStatus !== '验收中' &&-->
                                                        <!--                                                                record.taskStatus !== '延期完成'-->
                                                        <!--                                                            "-->
                                                        <!--                                                            key="6"-->
                                                        <!--                                                        >-->
                                                        <!--                                                            <a-button-->
                                                        <!--                                                                size="small"-->
                                                        <!--                                                                type="link"-->
                                                        <!--                                                                ghost-->
                                                        <!--                                                                :disabled="testImprovementDisabled(record)"-->
                                                        <!--                                                                @click="handleCheck(record, '提测')"-->
                                                        <!--                                                            >-->
                                                        <!--                                                                提测-->
                                                        <!--                                                            </a-button>-->
                                                        <!--                                                        </a-menu-item>-->

                                                        <!--                                                        &lt;!&ndash; 验收 &ndash;&gt;-->
                                                        <!--                                                        <a-menu-item-->
                                                        <!--                                                            v-if="-->
                                                        <!--                                                                record.taskType !== '问题' &&-->
                                                        <!--                                                                record.taskStatus === '测试中'-->
                                                        <!--                                                            "-->
                                                        <!--                                                            key="7"-->
                                                        <!--                                                        >-->
                                                        <!--                                                            <a-button-->
                                                        <!--                                                                size="small"-->
                                                        <!--                                                                type="link"-->
                                                        <!--                                                                ghost-->
                                                        <!--                                                                :disabled="checkDisabled(record)"-->
                                                        <!--                                                                @click="handleCheck(record, '验收')"-->
                                                        <!--                                                            >-->
                                                        <!--                                                                验收-->
                                                        <!--                                                            </a-button>-->
                                                        <!--                                                        </a-menu-item>-->

                                                        <!-- 预警 -->
                                                        <a-menu-item key="1" v-permission="'50001252_vid_p5orovs8fg'">
                                                            <a-button
                                                                size="small"
                                                                type="link"
                                                                @click="handlerWarning(record)"
                                                            >
                                                                预警
                                                            </a-button>
                                                        </a-menu-item>

                                                        <!-- 备注 -->
                                                        <a-menu-item key="2" v-permission="'50001252_vid_7zflzaojcs'">
                                                            <a-button
                                                                size="small"
                                                                type="link"
                                                                @click="handlerShowNotes(record)"
                                                            >
                                                                备注
                                                            </a-button>
                                                        </a-menu-item>
                                                        <a-menu-item v-permission="'50001252_vid_5g85oik90q'">
                                                            <a-button
                                                                size="small"
                                                                type="link"
                                                                @click="showChangeLog(record)"
                                                                >变更记录</a-button
                                                            >
                                                        </a-menu-item>
                                                    </a-menu>
                                                </template>
                                                <a-button size="small" type="link" v-if="record.taskType !== '问题'">
                                                    更多
                                                    <EllipsisOutlined
                                                        style="rotate: 90deg; font-size: 14px; margin: 0"
                                                    />
                                                </a-button>
                                            </a-dropdown>
                                        </a-space>
                                    </template>
                                </template>
                            </a-table>
                        </template>
                    </a-table>
                </div>
            </div>
            <!-- end vid_74h0kaeyby 自定义模板_ot1oz7qqmz -->
        </a-spin>
    </div>
</template>
<script setup lang="tsx">
    import {
        h,
        ref,
        reactive,
        toRaw,
        markRaw,
        watch,
        computed,
        onBeforeMount,
        onMounted,
        onBeforeUnmount,
        onUnmounted,
        onActivated,
        onDeactivated
    } from 'vue'
    import { useRoute, useRouter } from 'vue-router'
    const router = useRouter()
    const route = useRoute()
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios'
    import {
        cloneDeep,
        localGet,
        merge,
        getDifferenceArray,
        traversalTreeStructure,
        checkCaseCondition,
        renderStringInTemplate,
        handleBreadcrumbJump,
        throttle,
        permission,
        getComponentParamsValue
    } from '@/utils/index'
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is'
    import dayjs from 'dayjs'
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart'
    import { message, notification, Modal } from 'ant-design-vue'
    import {
        propertyFormatByNumber,
        propertyFormatByPercentage,
        propertyFormatByDate,
        parseSubFromDataList
    } from '@/utils/format'
    import colorTheme from '@/design/custom-theme.json'
    import { QuillEditor } from '@vueup/vue-quill'
    /*** PUBLISH_EXEGESIS ***
 import UserTableRecords from '@/model/UserTableRecords';
 import { getAppBaseUrl } from '@/utils/index';
 import { sendToken } from "@/hooks/useIframeToken";
 import { useSystemStore } from "@/store/modules/system";
 const systemStore = useSystemStore();
 *** PUBLISH_EXEGESIS ***/

    // 获取传入的流程ID和组件参数
    const props = defineProps({
        'processInstanceId': {
            type: [String, Number, Boolean],
            default: undefined
        },
        'projectId': {
            type: [String, Number],
            default: undefined
        },
        activeKey: String,
        refreshCount: Number
    })
    const immediateWatch = (source, callback) => {
        watch(source, callback, { deep: true, immediate: true })
    }

    /* -------------------------- 属性定义 -------------------------- */

    const setTimeOutList = []
    const pageLoading = reactive({
        loading: false,
        tip: undefined
    })
    const authInfo = localGet('app-user-store')

    // 处理校验
    const setSubFormName = (parentInfo, name) => {
        return [parentInfo.parents, parentInfo.cycleIndex, name]
    }

    /* ========================== 属性定义 ========================== */

    /* -------------------------- 元素数据引用 -------------------------- */

    /* ========================== 元素数据引用 ========================== */

    /* -------------------------- 页面数据 -------------------------- */

    /* ========================== 页面数据 ========================== */

    /* -------------------------- 响应 -------------------------- */

    /* ========================== 响应 ========================== */

    /* -------------------------- 函数 -------------------------- */

    /* ========================== 函数 ========================== */

    /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId
    })

    /* ========================== 页面参数 ========================== */

    /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================

    /* ========================== 组件事件处理方法 ========================== */

    /* -------------------------- 生命周期 -------------------------- */
    // 用于参数变更后重新执行自定义指令
    const queryUpdateFlag = ref(0)
    onMounted(() => {})

    onUnmounted(() => {
        // 销毁定时器
        setTimeOutList.forEach(({ repeat, timer }) => {
            repeat ? clearInterval(timer) : clearTimeout(timer)
        })
    })

    /* ========================== 生命周期 ========================== */

    /* -------------------------- 数据关联处理 -------------------------- */

    /* -------------------------- 表单数据同步 -------------------------- */
    /* ========================== 表单数据同步 ========================== */

    /* ========================== 数据关联处理 ========================== */

    /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

    /* ========================== 不同组件自定义的处理逻辑 ========================== */

    // ================================定制化逻辑========================================
    // 判断 URL 是否带有 jump 参数
    const hasJump = computed(() => !!route.query.jump)
    const headerOffset = ref(150)
    const calcTableHeight = () => {
        state.tableHeight = window.innerHeight - 180 - headerOffset.value
    }

    onMounted(() => {
        calcTableHeight()
        window.addEventListener('resize', calcTableHeight)

        document.addEventListener('click', e => {
            const target = e.target as HTMLElement
            if (target.tagName === 'IMG' && target.classList.contains('previewable-image')) {
                const imgUrl = target.getAttribute('src')
                if (imgUrl) {
                    // 预览逻辑，如弹窗显示 imgUrl
                    previewImage(imgUrl)
                }
            }
        })
    })

    onBeforeUnmount(() => {
        window.removeEventListener('resize', calcTableHeight)
    })
    function previewImage(url) {
        const imgWindow = window.open()
        if (imgWindow) {
            imgWindow.document.write(`<img src="${url}" style="max-width:100%"/>`)
        }
    }
    const columns = ref([
        {
            title: '用户故事名称',
            dataIndex: 'storyName',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 440,
            fixed: 'left',
            visible: true
        },
        {
            title: '所属子目标',
            dataIndex: 'projectMonthlyGoal',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 200,
            visible: computed(() => showState.storyCheckList.includes('所属子目标'))
        },
        {
            title: '版本号',
            dataIndex: 'iterationVersionName',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.storyCheckList.includes('用户故事状态'))
        },
        {
            title: '用户故事状态',
            dataIndex: 'storyStatus',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.storyCheckList.includes('用户故事状态'))
        },
        {
            title: '进度',
            dataIndex: 'progress',
            align: 'center',
            ellipsis: true,
            width: 220,
            visible: computed(() => showState.storyCheckList.includes('进度'))
        },
        {
            title: '优先级',
            dataIndex: 'priority',
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.storyCheckList.includes('优先级'))
        },
        {
            title: '负责人',
            dataIndex: 'owner',
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.storyCheckList.includes('负责人'))
        },

        {
            title: '计划开始',
            dataIndex: 'startTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.storyCheckList.includes('计划开始'))
        },
        {
            title: '实际开始',
            dataIndex: 'actualStartTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.storyCheckList.includes('实际开始'))
        },
        {
            title: '计划完成',
            dataIndex: 'endTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.storyCheckList.includes('计划完成'))
        },
        {
            title: '实际完成',
            dataIndex: 'actualEndTime',
            align: 'center',
            ellipsis: true,
            width: 200,
            visible: computed(() => showState.storyCheckList.includes('实际完成'))
        },
        {
            title: '最新备注',
            dataIndex: 'remarks',
            align: 'center',
            ellipsis: true,
            resizable: true,
            width: 200,
            visible: computed(() => showState.storyCheckList.includes('最新备注'))
        },
        {
            title: '创建人',
            dataIndex: 'createdBy',
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.storyCheckList.includes('创建人'))
        },
        {
            title: '创建时间',
            dataIndex: 'createdTime',
            align: 'center',
            ellipsis: true,
            width: 200,
            visible: computed(() => showState.storyCheckList.includes('创建时间'))
        },
        { title: '操作', align: 'center', dataIndex: 'fatherOperation', width: 170, fixed: 'right' }
    ])
    const innerColumns = ref([
        {
            title: '任务名称',
            dataIndex: 'taskName',
            align: 'center',
            ellipsis: true,
            resizable: true,
            width: 320,
            fixed: 'left',
            visible: true
        },
        {
            title: '任务状态',
            dataIndex: 'taskStatus',
            align: 'center',
            resizable: true,
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('任务状态'))
        },
        {
            title: '优先级',
            dataIndex: 'priority',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.taskCheckList.includes('优先级'))
        },
        {
            title: '审核标准',
            dataIndex: 'assessorStandard',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.taskCheckList.includes('审核标准'))
        },
        {
            title: '任务负责人',
            dataIndex: 'taskOwner',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('任务负责人'))
        },
        {
            title: '任务执行人',
            dataIndex: 'taskParticipant',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('任务执行人'))
        },
        {
            title: '审核员',
            dataIndex: 'assessorName',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.taskCheckList.includes('审核员'))
        },
        {
            title: '计划开始',
            dataIndex: 'startTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('计划开始'))
        },
        {
            title: '实际开始',
            dataIndex: 'examPassTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('实际开始'))
        },
        {
            title: '计划完成',
            dataIndex: 'endTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('计划完成'))
        },
        {
            title: '实际完成',
            dataIndex: 'taskFinishTime',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('实际完成'))
        },
        {
            title: '计划工时',
            dataIndex: 'workingHours',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('计划工时'))
        },
        {
            title: '实际工时',
            dataIndex: 'actualWorkHours',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('实际工时'))
        },
        {
            title: '附件模板',
            dataIndex: 'attachmentTemplateList',
            align: 'center',
            ellipsis: true,
            width: 120,
            visible: computed(() => showState.taskCheckList.includes('附件模板'))
        },
        {
            title: '附件',
            dataIndex: 'attachmentList',
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.taskCheckList.includes('附件'))
        },
        {
            title: '最新备注',
            dataIndex: 'description',
            resizable: true,
            align: 'center',
            ellipsis: true,
            width: 200,
            visible: computed(() => showState.storyCheckList.includes('最新备注'))
        },
        {
            title: '创建人',
            dataIndex: 'createBy',
            align: 'center',
            ellipsis: true,
            width: 80,
            visible: computed(() => showState.taskCheckList.includes('创建人'))
        },
        {
            title: '创建时间',
            dataIndex: 'createTime',
            align: 'center',
            ellipsis: true,
            width: 200,
            visible: computed(() => showState.taskCheckList.includes('创建时间'))
        },
        {
            title: '操作',
            align: 'left',
            dataIndex: 'operation',
            width: 179,
            fixed: 'right'
        }
    ])
    const displayStoryColumns = computed(() =>
        columns.value.filter(col => {
            return typeof col.visible === 'boolean' ? col.visible : col.visible?.value ?? true // 兼容直接写 true / false 或 computed
        })
    )
    const displayTaskColumns = computed(() =>
        innerColumns.value.filter(col => {
            return typeof col.visible === 'boolean' ? col.visible : col.visible?.value ?? true // 兼容直接写 true / false 或 computed
        })
    )
    // 获取所有数据
    function getData() {
        if (!useProjectId.value) {
            message.info('请选择项目')
            return
        }

        state.tableLoading = true
        post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/story_task_list', {
            projectId: useProjectId.value,
            ...state.filter
        })
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    state.dataSource = []
                    return
                }
                state.dataSource = data.data
                const storyKeys = []
                const taskKeys = {}

                state.dataSource.forEach(story => {
                    if (story.keynote === '是') {
                        storyKeys.push(story.id)
                    }
                    if (story.taskChildrenList?.length) {
                        const selectedChildren = story.taskChildrenList
                            .filter(t => t.keynote === '是')
                            .map(t => t.taskId)
                        if (selectedChildren.length > 0) {
                            taskKeys[story.id] = selectedChildren
                        }
                    }
                })

                state.selectedStoryKeys = storyKeys
                state.selectedTaskKeys = taskKeys
            })
            .finally(() => {
                state.tableLoading = false
            })
    }
    const userInfoStorage = localStorage.getItem('al__USER_INFO')
    const taskLeader = JSON.parse(userInfoStorage)
    // 解析 window.location.search
    function parseSearchParams() {
        const search = window.location.search.substring(1)
        const params = new URLSearchParams(search)
        const result: Record<string, string> = {}
        params.forEach((value, key) => {
            result[key] = value
        })
        return result
    }

    // 统一入口参数，优先级：props > route.query > window.location.search
    const effectiveParams = computed(() => {
        return {
            ...parseSearchParams(),
            ...route.query,
            ...props
        }
    })
    const peopleList = ref([])
    const expanded = ref(false)
    // 页面整体数据控制
    const state = reactive({
        filter: {
            storyId: undefined,
            storyDirectionField: 'story_name-asc',
            directionField: 'created_time-desc',
            storyLabels: undefined,
            storyStatus: undefined,
            taskType: undefined,
            storyEndTimeList: [],
            endTimeList: [],
            iterationVersionId: null,
            taskStatus: undefined
        },
        dataSource: [],
        versionList: [],
        filterVersionList: [],
        showCheck: false,
        expendAll: false,
        tableLoading: false,
        expandedRowKeys: [],
        tableHeight: 400,
        selectedStoryKeys: [], // 外层（父表）勾选的
        selectedTaskKeys: {}, // 内层（子表）勾选的，按父 id 分组
        taskOptions: [
            {
                label: '未启动',
                value: '未启动'
            },
            {
                label: '进行中',
                value: '进行中'
            },
            {
                label: '测试中',
                value: '测试中'
            },
            {
                label: '验收中',
                value: '验收中'
            },
            {
                label: '完成',
                value: '完成'
            }
        ]
    })
    function getAllVersion() {
        post('/solution-ppm/api/v2/built-in-system-ppm/iteration_version/list_by_project', {
            projectId: useProjectId.value
        }).then(data => {
            state.versionList = data.data
                .filter(ver => ver.status === '未发布')
                .map(item => {
                    return {
                        label: item.version,
                        value: item.id
                    }
                })
        })
    }
    function getFilterVersion() {
        get(`/solution-ppm/api/v2/built-in-system-ppm/project/story/iteration_version_list/${useProjectId.value}`).then(
            data => {
                state.filterVersionList = data.data
            }
        )
    }
    // 获取用户的显示设置
    function getPeopleSetting() {
        get(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/person_config/search`).then(data => {
            showState.taskCheckList = data.data.taskCheckList || []
            showState.storyCheckList = data.data.storyCheckList || []
            updateAllCheckStates()
        })
    }
    // 保存用户显示设置
    function confirmSetting() {
        showState.settingLoading = true
        post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/person_config/create', {
            taskCheckList: showState.taskCheckList,
            storyCheckList: showState.storyCheckList
        })
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                message.success(data.message)
                showState.settingVisible = false
            })
            .finally(() => {
                showState.settingLoading = false
            })
    }
    // 更新所有全选状态
    function updateAllCheckStates() {
        showState.storyAllCheck = showState.storyCheckList.length === showState.allStoryOptions.length
        showState.taskAllCheck = showState.taskCheckList.length === showState.allTaskOptions.length
    }
    const showState = reactive({
        storyCheckList: [],
        taskCheckList: [],
        storyAllCheck: false,
        allStoryOptions: getStoryOptions(),
        allTaskOptions: getTaskOptions(),
        taskAllCheck: false,
        settingVisible: false,
        settingLoading: false
    })
    function getStoryOptions() {
        return columns.value.filter(c => !['操作', '用户故事名称', '版本号'].includes(c.title)).map(c => c.title)
    }

    function getTaskOptions() {
        return innerColumns.value.filter(c => !['操作', '任务名称'].includes(c.title)).map(c => c.title)
    }

    const handlerShowCheck = async () => {
        if (!state.showCheck) {
            // 打开勾选模式
            state.showCheck = true
            // 保存初始状态，用于之后比较差异
            state.initialStoryKeys = cloneDeep(state.selectedStoryKeys)
            state.initialTaskKeys = cloneDeep(state.selectedTaskKeys)
        } else {
            // 保存
            try {
                state.keyNoteLoading = true

                // ---- 整理父级 story 的新增/删除 ----
                const addedStories = state.selectedStoryKeys.filter(key => !state.initialStoryKeys.includes(key))
                const removedStories = state.initialStoryKeys.filter(key => !state.selectedStoryKeys.includes(key))

                // ---- 整理子级 task 的新增/删除 ----
                const addedTasks = []
                const removedTasks = []

                // 遍历每个 story 下的任务
                const allStoryIds = new Set([
                    ...Object.keys(state.initialTaskKeys),
                    ...Object.keys(state.selectedTaskKeys)
                ])

                allStoryIds.forEach(storyId => {
                    const oldKeys = state.initialTaskKeys[storyId] || []
                    const newKeys = state.selectedTaskKeys[storyId] || []

                    // 新增
                    newKeys.forEach(taskId => {
                        if (!oldKeys.includes(taskId)) {
                            addedTasks.push(taskId)
                        }
                    })
                    // 删除
                    oldKeys.forEach(taskId => {
                        if (!newKeys.includes(taskId)) {
                            removedTasks.push(taskId)
                        }
                    })
                })

                // ---- 调用两个接口 ----
                const [storyRes, taskRes] = await Promise.all([
                    put(`/solution-ppm/api/v2/built-in-system-ppm/project/story/keynote_story/${useProjectId.value}`, {
                        addedKeynotes: addedStories,
                        removedKeynotes: removedStories
                    }),
                    put(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/keynote_task/${useProjectId.value}`, {
                        addedKeynotes: addedTasks,
                        removedKeynotes: removedTasks
                    })
                ])

                if (storyRes.code === 200 && taskRes.code === 200) {
                    message.success('保存成功')
                    state.showCheck = false
                    getData() // 刷新表格
                } else {
                    message.error('保存失败')
                }
            } catch (e) {
                message.error('保存失败')
            } finally {
                state.keyNoteLoading = false
            }
        }
    }
    const storyRowSelection = computed(() => {
        return state.showCheck
            ? {
                  selectedRowKeys: state.selectedStoryKeys,
                  onChange: keys => {
                      state.selectedStoryKeys = keys
                  }
              }
            : null
    })
    const keyNoteLoading = ref(false)
    const payload = {
        stories: state.selectedStoryKeys,
        tasks: state.selectedTaskKeys
    }
    // 页面整体数据控制
    // 初始化/监听变化
    const useProjectId = ref()
    function initPage(params) {
        useProjectId.value = params.projectId || params.id

        state.filter.storyId = Number(params.storyId) || undefined
        state.filter.iterationVersionId = Number(params.iterationVersionId) || undefined

        // if (params.taskStatus && params.taskStatus !== '总数') {
        //     state.filter.taskStatus = params.taskStatus
        // } else {
        //     state.filter.taskStatus = undefined
        // }

        // 统一请求方法
        getAllVersion()
        getFilterVersion()
        getStory()
        getTemplateCode()
        getPopleList()
        getAllJfPeople()
        getStatusList()
        getLabelList()
        getData()
        getPeopleSetting()
    }

    // 监听入口参数 + 父页面传递的 activeKey / refreshCount
    watch(
        () => [effectiveParams.value, props.activeKey, props.refreshCount],
        ([params]) => {
            console.log('生效的参数：', params)
            initPage(params)
        },
        { immediate: true }
    )
    const reset = () => {
        state.filter = {
            storyId: undefined,
            storyDirectionField: 'story_name-asc',
            directionField: 'created_time-desc',
            storyLabels: undefined,
            storyStatus: undefined,
            taskType: undefined,
            storyEndTimeList: [],
            endTimeList: [],
            iterationVersionId: null,
            taskStatus: undefined
        }
        getData()
    }

    function showSetting() {
        showState.settingVisible = true
    }
    // 监听单个用户故事选项的变化
    const handleStoryCheckChange = () => {
        showState.storyAllCheck = showState.storyCheckList.length === showState.allStoryOptions.length
    }
    // 用户故事全选
    function storyAllChange() {
        showState.storyCheckList = showState.storyAllCheck ? [...showState.allStoryOptions] : []
    }
    // 监听单个任务故事选项的变化
    const handleTaskCheckChange = () => {
        showState.taskAllCheck = showState.taskCheckList.length === showState.allTaskOptions.length
    }
    // 用户故事全选
    function taskAllChange() {
        showState.taskCheckList = showState.taskAllCheck ? [...showState.allTaskOptions] : []
    }
    const finishPercent = item => {
        const total = item.taskNumber || 1
        return ((item.finishTaskNumber / total) * 100).toFixed(2)
    }

    const totalPercent = item => {
        const total = item.taskNumber || 1
        return (((item.finishTaskNumber + item.runningTaskNumber) / total) * 100).toFixed(2)
    }

    //     用户故事部分=====================================================================================================================================================================================
    //     用户故事部分=====================================================================================================================================================================================
    //     用户故事部分=====================================================================================================================================================================================
    const inputHolder = '请输入'
    const selectHolder = '请选择'
    function handleResizeStoryColumn(w, col) {
        col.width = w
    }

    const milepostState = reactive({
        searchForm: {
            storyStatus: undefined,
            storyName: undefined,
            directionField: 'created_time-desc',
            labels: undefined
        },
        sortList: [
            {
                label: '用户故事名称正序',
                value: 'story_name-asc'
            },
            {
                label: '用户故事名称倒序',
                value: 'story_name-desc'
            },
            {
                label: '创建时间正序',
                value: 'created_time-asc'
            },
            {
                label: '创建时间倒序',
                value: 'created_time-desc'
            },
            {
                label: '计划完成时间正序',
                value: 'end_time-asc'
            },
            {
                label: '计划完成时间倒序',
                value: 'end_time-desc'
            },
            {
                label: '计划开始时间正序',
                value: 'start_time-asc'
            },
            {
                label: '计划开始时间倒序',
                value: 'start_time-desc'
            },
            {
                label: '优先级正序',
                value: 'priority-asc'
            },
            {
                label: '优先级倒序',
                value: 'priority-desc'
            }
        ],
        dataList: [],
        treeData: [],
        targetKeys: [],
        selectKeys: [],
        SopTaskList: [],
        addOrEditVisible: false,
        dataLoading: false,
        nextLoading: false,
        okLoading: false,
        addOrEditTitle: '',
        modalForm: {
            storyName: undefined,
            priority: undefined,
            labels: undefined,
            ownerList: [taskLeader.value.name],
            iterationVersionId: undefined,
            timeRangeList: [],
            taskList: [],
            templateTaskId: [],
            monthlyGoalTargetMonth: undefined,
            projectMonthlyGoalManagementId: undefined,
            remarks: undefined
        },
        current: 1,
        statusList: [],
        projectTreeList: [],
        labelList: [],
        showCheck: false,
        keyNoteLoading: false,
        targetList: [],
        parentName: undefined,
        transferVisible: false,
        transferLoading: false,
        transferId: undefined,
        correlationVisible: false,
        correlationLoading: false,
        correlationId: undefined,
        correlationSelectKeys: [],
        correlationData: [],
        correlationTableLoading: false,
        correlationNewData: [],
        allDemand: []
    })

    const storyFormRef = ref(null)
    const storyRules = {
        storyName: [
            {
                required: true,
                message: '请输入用户故事名称',
                trigger: 'blur'
            }
        ],
        allTime: [{ required: false, message: '请选择计划起止时间!', trigger: 'blur' }],
        iterationVersionId: [{ required: false, message: '!', trigger: 'blur' }],
        ownerList: [{ required: true, message: '请选择负责人!', trigger: 'blur' }]
        // functionAbbreviation: [{ required: true, message: '请输入功能简称', trigger: 'blur' }]
    }
    const currentStoryData = ref({})
    // 新建用户故事弹窗
    function handleAdd() {
        if (!useProjectId.value) {
            message.info('请选择项目')
            return
        }
        milepostState.addOrEditVisible = true

        milepostState.addOrEditTitle = '新建用户故事'
        milepostState.modalForm.ownerList = [taskLeader.value.name]
        currentStoryData.value = {}
    }
    //     新建下一步获取任务
    function getTaskStory() {
        storyFormRef.value.validate().then(() => {
            createSopDeltaDate.value = storyQuillEditor.value.getContents()
            milepostState.nextLoading = true
            post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/generate_task', {
                templateTaskId: milepostState.modalForm.templateTaskId,
                storyId: milepostState.modalForm.storyId,
                functionAbbreviation: milepostState.modalForm.functionAbbreviation,
                projectId: useProjectId.value
            })
                .then(data => {
                    milepostState.current = 2
                    milepostState.modalForm.taskList = data.data.map(item => {
                        return {
                            ...item,
                            allTime: [item.startTime, item.endTime]
                        }
                    })
                })
                .finally(() => {
                    milepostState.nextLoading = false
                })
        })
    }
    const taskPeopleList = ref([])
    function getPopleList() {
        post(`/solution-ppm/api/v2/built-in-system-ppm/task/getTopUser/${useProjectId.value}`).then(data => {
            taskPeopleList.value = data.data.map(item => {
                return {
                    label: item,
                    value: item
                }
            })
        })
    }

    function getAllJfPeople() {
        get('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser').then(({ data }) => {
            peopleList.value = data.userDtoList.map(item => {
                return {
                    label: item.name,
                    value: item.name
                }
            })
        })
    }
    // 用户故事新建任务快捷添加执行人
    function handlerAddPtMbPeople(name, index) {
        if (milepostState.modalForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
            milepostState.modalForm.taskList[index].taskParticipantList = milepostState.modalForm.taskList[
                index
            ].taskParticipantList.filter(item => item !== name)
        } else {
            milepostState.modalForm.taskList[index].taskParticipantList.push(name)
        }
        getStoryTaskParticipantList('modalForm', index)
    }
    function cancelStory() {
        currentStoryData.value = {}
        milepostState.addOrEditVisible = false
        milepostState.modalForm = {
            storyName: undefined,
            priority: undefined,
            labels: undefined,
            timeRangeList: [],
            taskList: [],
            templateTaskId: [],
            monthlyGoalTargetMonth: undefined,
            projectMonthlyGoalManagementId: undefined,
            remarks: undefined
        }
        milepostState.current = 1
    }
    const projectTemplate = ref()
    function getTemplateCode() {
        get(`/solution-ppm/api/v2/built-in-system-ppm/platform_product/product_project/${useProjectId.value}`).then(
            data => {
                console.log(data)
                projectTemplate.value = data.data.projectTemplate
                milepostState.parentName = data.data.parentId
            }
        )
    }
    //     获取穿梭框
    function getTreeData() {
        get(
            `/solution-ppm/api/v2/built-in-system-ppm/v2/platform/template_milepost_task?templateCode=${projectTemplate.value}&functionAbbreviation=${milepostState.modalForm.functionAbbreviation}&projectId=${useProjectId.value}`
        ).then(data => {
            milepostState.treeData = data.data
            taskState.treeData = data.data
            console.log(milepostState.treeData)
            milepostState.modalForm.selectKeys = []
            taskState.modalForm.selectKeys = []
        })
    }
    const storyQuillEditor = ref(null)
    const createSopDeltaDate = ref()
    // 保存模板项目
    function storyConfirmMbTask() {
        storyFormRef.value.validate().then(async () => {
            milepostState.okLoading = true
            milepostState.modalForm.taskList.forEach(item => {
                item.startTime = item.allTime[0]
                item.endTime = item.allTime[1]
            })

            let deltaContent = undefined
            if (currentStoryData.value.id) {
                deltaContent = storyQuillEditor.value.getContents()
            } else {
                if (milepostState.current === 1) {
                    deltaContent = storyQuillEditor.value.getContents()
                } else {
                    deltaContent = createSopDeltaDate.value
                }
            }
            // const deltaContent = currentStoryData.value.id ? storyQuillEditor.value.getContents() : createSopDeltaDate.value

            const imageUploadPromises = []
            deltaContent.ops.forEach(op => {
                if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                    const localSrc = op.insert.image

                    // 如果是 base64 图片，上传并替换为 URL
                    const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                    const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                        // 替换 op 中的 base64 URL 为服务器返回的 URL
                        op.insert.image = fullUrl
                    })

                    imageUploadPromises.push(uploadPromise)
                }
            })

            const api = currentStoryData.value.id ? put : post
            try {
                await Promise.all(imageUploadPromises)
                api(`/solution-ppm/api/v2/built-in-system-ppm/project/story`, {
                    projectId: useProjectId.value,
                    timeRangeList: milepostState.modalForm.timeRangeList,
                    storyName: milepostState.modalForm.storyName,
                    ppmPlatformTaskFormList: milepostState.modalForm.taskList,
                    id: currentStoryData.value.id,
                    priority: milepostState.modalForm.priority,
                    labels: milepostState.modalForm.labels,
                    description: JSON.stringify(deltaContent),
                    monthlyGoalTargetMonth: milepostState.modalForm.monthlyGoalTargetMonth,
                    projectMonthlyGoalManagementId: milepostState.modalForm.projectMonthlyGoalManagementId,
                    remarks: milepostState.modalForm.remarks,
                    iterationVersionId: milepostState.modalForm.iterationVersionId,
                    ownerList: milepostState.modalForm.ownerList
                })
                    .then(data => {
                        if (data.code !== 200) {
                            message.error(data.message)
                            return
                        }
                        message.success(data.message)

                        storyCancleMbTask()

                        getData()
                    })
                    .finally(() => {
                        milepostState.okLoading = false
                    })
            } catch (error) {
                milepostState.okLoading = false
                console.error('图片上传失败', error)
                return // 终止提交
            }
        })
    }
    // 关闭模板任务新建
    function storyCancleMbTask() {
        milepostState.addOrEditVisible = false
        milepostState.current = 1
        milepostState.modalForm.functionAbbreviation = undefined
        milepostState.modalForm.templateTaskId = undefined
        milepostState.modalForm = {
            templateTaskId: [],
            projectId: useProjectId.value,
            functionAbbreviation: undefined,
            taskList: []
        }
    }
    function confirmDelete(id) {
        del(`/solution-ppm/api/v2/built-in-system-ppm/project/story/${id}`).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            message.success(data.message)
            getData()
        })
    }
    function useDebounce(fn: (...args: any[]) => void, delay = 500) {
        let timer: ReturnType<typeof setTimeout> | null = null

        return function (...args: any[]) {
            if (timer) clearTimeout(timer)
            timer = setTimeout(() => {
                fn(...args)
            }, delay)
        }
    }
    // 包一层防抖函数
    const debounceGetData = useDebounce(getData, 500)
    //     编辑story
    async function handleEditStory(record) {
        const item = cloneDeep(record)
        Object.assign(milepostState.modalForm, item)
        milepostState.modalForm.timeRangeList = !item.startTime || !item.endTime ? [] : [item.startTime, item.endTime]
        currentStoryData.value = item
        milepostState.addOrEditVisible = true
        milepostState.addOrEditTitle = '编辑用户故事'
        getTarget()
        getAllVersion()
        nextTick(() => {
            let descriptionData = JSON.parse(record.description)

            storyQuillEditor?.value?.setContents(descriptionData)
        })
    }
    function getTarget() {
        post('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/monthlyGoals', {
            targetMonthList: [
                milepostState.modalForm.monthlyGoalTargetMonth,
                milepostState.modalForm.monthlyGoalTargetMonth
            ],
            projectId: milepostState.parentName
        }).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            const allSubGoals = []

            data.data.monthlyGoalManagementDtoList?.forEach(item => {
                item.monthlyGoalTaskDtoList?.forEach(sub => {
                    allSubGoals.push({
                        label: sub.projectMonthlyGoal,
                        value: sub.id
                    })
                })
            })
            milepostState.targetList = allSubGoals
        })
    }
    function getStatusList() {
        get(' /solution-ppm-basic-data/api/v1/dictionary/search/PTYHGS.RWZT').then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            milepostState.statusList = taskState.statusList = data.data.map(item => {
                return {
                    label: item.itemName,
                    value: item.itemCode
                }
            })
        })
    }
    function handlerGetSpace(data) {
        return data?.split(/[,;；]/)
    }
    function getLabelList() {
        get(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/story_labels/${useProjectId.value}`).then(
            data => {
                milepostState.labelList = data.data
            }
        )
    }
    // 根据id查目录

    //     增加富文本
    //     富文本设置
    import { nextTick } from 'vue'
    import { QuillEditor, Quill } from '@vueup/vue-quill'
    import ImageUploader from 'quill-image-uploader'
    import '@vueup/vue-quill/dist/vue-quill.snow.css'
    const titleConfig = [
        { Choice: ' .ql-bold', title: '加粗' },
        { Choice: ' .ql-italic', title: '斜体' },
        { Choice: ' .ql-underline', title: '下划线' },
        { Choice: ' .ql-strike', title: '删除线' },
        { Choice: ' .ql-blockquote', title: '块引用' },
        { Choice: ' .ql-code-block', title: '插入代码' },
        { Choice: ' .ql-size', title: '字体大小' },
        { Choice: ' .ql-size', title: '字体大小' },
        { Choice: ' .ql-color', title: '字体颜色' },
        { Choice: ' .ql-background', title: '字体背景颜色' },
        { Choice: ' .ql-list[value="ordered"]', title: '有序列表' },
        { Choice: ' .ql-list[value="bullet"]', title: '无序列表' },
        { Choice: ' .ql-header[value="1"]', title: '1级标题' },
        { Choice: ' .ql-header[value="2"]', title: '2级标题' },
        { Choice: ' .ql-align', title: '对齐方式' },
        { Choice: ' .ql-clean', title: '清除字体格式' },
        { Choice: ' .ql-image', title: '图像' },
        { Choice: ' .ql-size .ql-picker-item[data-value="small"]', title: '小号' },
        { Choice: ' .ql-size .ql-picker-item[data-value="large"]', title: '大号' },
        { Choice: ' .ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
        { Choice: ' .ql-size .ql-picker-item:nth-child(2)', title: '标准' },
        { Choice: ' .ql-align .ql-picker-item:first-child', title: '居左对齐' },
        { Choice: ' .ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
        { Choice: ' .ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
        { Choice: ' .ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
    ]
    // 注册图片上传模块
    Quill.register('modules/imageUploader', ImageUploader)

    // 将本地文件转换为URL
    const getLocalImageURL = file => {
        return new Promise(resolve => {
            const reader = new FileReader()
            reader.onload = e => {
                resolve(e.target.result)
            }
            reader.readAsDataURL(file)
        })
    }

    // 表单数据

    // Quill 编辑器选项
    const editorOption = ref({
        modules: {
            // imageUploader: {
            //     upload: async file => {
            //         const localUrl = await getLocalImageURL(file)
            //         return localUrl // 返回本地图片的 URL 进行预览
            //     }
            // },
            toolbar: [
                ['bold', 'italic', 'underline', 'strike'], // 加粗，斜体，下划线，删除线
                ['blockquote', 'code-block'], // 引用，代码块
                [{ header: 1 }, { header: 2 }], // 标题1，标题2
                [{ list: 'ordered' }, { list: 'bullet' }], // 有序列表，无序列表
                [{ size: ['small', false, 'large', 'huge'] }], // 文字大小
                [{ color: [] }, { background: [] }], // 字体颜色，背景颜色
                [{ align: [] }], // 对齐
                ['clean'], // 清除格式
                ['image'] // 链接，图片，视频
            ]
            // ImageUploader: imageHandler
        }
    })
    // 上传API
    const uploadFileAPI = async file => {
        const data = new FormData()
        data.append('file', file)

        return post('/file-storage/api/v1/file/upload', data)
            .then(({ data: { fullUrl } }) => {
                return { data: { fullUrl } }
            })
            .catch(error => {
                console.error('上传图片出错:', error)
                throw error // 抛出错误以供外部处理
            })
    }

    // 将 dataURL 转换为 File 对象的辅助函数
    const dataURLtoFile = (dataurl, filename) => {
        const arr = dataurl.split(',')
        const mime = arr[0].match(/:(.*?);/)[1]
        const bstr = atob(arr[1])
        let n = bstr.length
        const u8arr = new Uint8Array(n)
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
        }
        return new File([u8arr], filename, { type: mime })
    }

    function initTitle() {
        document.getElementsByClassName('ql-editor')[0].dataset.placeholder = ''
        for (let item of titleConfig) {
            let tip = document.querySelector('.ql-toolbar' + item.Choice)
            if (!tip) continue
            tip.setAttribute('title', item.title)
        }
    }
    function showQuestionMsg(msg) {
        if (!msg) {
            message.info('暂无描述')
            return
        }
        showMsgState.msg = msg
        showMsgState.visible = true
    }
    function cancelShowMsg() {
        showMsgState.msg = undefined
        showMsgState.visible = false
    }
    //   格式化文本展示
    import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'
    function getHtmlContent(input) {
        if (!input) return ''
        let deltaObj = null
        try {
            const parsed = typeof input === 'string' ? JSON.parse(input) : input
            if (parsed?.ops && Array.isArray(parsed.ops)) {
                deltaObj = parsed
            }
        } catch (e) {}

        if (deltaObj) {
            try {
                const converter = new QuillDeltaToHtmlConverter(deltaObj.ops, {
                    inlineStyles: false
                })
                let html = converter.convert()

                // 预览支持：用原生 <img> 包裹在一个带点击预览功能的 <a> 中
                html = html.replace(/<img[^>]*src="([^"]+)"[^>]*>/g, (match, src) => {
                    return `<img src="${src}" class="previewable-image" title="点击查看图片"/>`
                })

                return html
            } catch (err) {
                console.error('富文本转HTML失败', err)
                return ''
            }
        }

        return String(input).replace(/\n/g, '<br/>')
    }
    const currentTransferRecord = ref()
    function showTransfer(record) {
        getProjectTreeList()
        currentTransferRecord.value = record
        milepostState.transferVisible = true
    }
    //     获取项目树
    async function getProjectTreeList() {
        await post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/project/tree', {
            projectName: state.treeSearchName
        }).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return false
            }
            // 接口返回的完整项目树
            const tree = data.data
            const parent = findParentNode(tree, useProjectId.value)

            if (parent) {
                console.log('遭到了')
                const siblings = parent.children.filter(c => c.projectId !== useProjectId.value)
                // 这里包装一层父节点，结构清晰
                milepostState.projectTreeDate = [
                    {
                        projectId: parent.projectId,
                        projectName: parent.projectName,
                        children: siblings
                    }
                ]
            } else {
                // 没找到父节点，就降级展示原始树
                milepostState.projectTreeDate = tree
            }

            return true
        })
    }
    // 递归查找父节点
    function findParentNode(tree, targetId) {
        for (const node of tree) {
            if (node.children && node.children.length) {
                // 判断当前节点的子节点中是否有目标ID
                const foundChild = node.children.find(child => child.projectId === targetId)
                if (foundChild) return node
                // 否则继续向下找
                const foundInChild = findParentNode(node.children, targetId)
                if (foundInChild) return foundInChild
            }
        }
        return null
    }

    function confirmTransfer() {
        if (!milepostState.transferId) {
            message.info('请选择迭代项目')
            return
        }
        milepostState.transferLoading = true
        put(
            `/solution-ppm/api/v2/built-in-system-ppm/project/story/transfer/${currentTransferRecord.value.id}/${milepostState.transferId}`
        )
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                message.success(data.message)
                cancelTransfer()
                getData()
            })
            .finally(() => {
                milepostState.transferLoading = false
            })
    }
    function cancelTransfer() {
        milepostState.transferVisible = false
        currentTransferRecord.value = {}
        milepostState.transferId = undefined
    }
    // 关联需求
    const currentCorrelationRecord = ref()
    function showCorrelation(record) {
        currentCorrelationRecord.value = record
        getAssociationRequirement()
        milepostState.correlationVisible = true
    }
    function getAssociationRequirement() {
        milepostState.correlationTableLoading = true
        get(
            `/solution-ppm/api/v2/built-in-system-ppm/project/story/requirement_list/${currentCorrelationRecord.value.id}`
        )
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                milepostState.correlationData = data.data
            })
            .finally(() => {
                milepostState.correlationTableLoading = false
            })
    }
    function confirmCorrelation() {
        if (
            !currentCorrelationRecord.value.number &&
            milepostState.correlationNewData.length == 0 &&
            milepostState.correlationSelectKeys.length == milepostState.correlationData.length
        ) {
            message.info('需求池转化的用户故事需至少关联一个需求池需求')
            return
        }
        milepostState.correlationLoading = true
        put(
            `/solution-ppm/api/v2//built-in-system-ppm/project/story/association_requirement/${currentCorrelationRecord.value.id}`,
            {
                'addedKeynotes': milepostState.correlationNewData,
                'removedKeynotes': milepostState.correlationSelectKeys
            }
        )
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                message.success(data.message)
                cancelCorrelation()
                getData()
            })
            .finally(() => {
                milepostState.correlationLoading = false
            })
    }
    function cancelCorrelation() {
        milepostState.correlationVisible = false
        currentCirculationData.value = {}
        milepostState.correlationId = undefined
    }
    function onSelectChange(selectedRowKeys) {
        milepostState.correlationSelectKeys = selectedRowKeys
    }
    const correlationColumns = ref([
        {
            dataIndex: 'number',
            title: '需求编号',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'labels',
            title: '标签',
            ellipsis: true,
            width: 200,
            align: 'center',
            resizable: true
        },

        {
            dataIndex: 'priority',
            title: '优先级',
            width: 150,
            ellipsis: true,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'proposer',
            title: '需求提出人',
            width: 120,
            ellipsis: true,
            align: 'center',
            resizable: true
        },
        {
            dataIndex: 'proposedTime',
            title: '提出时间',
            ellipsis: true,
            width: 150,
            align: 'center',
            resizable: true
        }
    ])
    function getAllDemand() {
        get(
            `/solution-ppm/api/v2/built-in-system-ppm/project/story/association_requirement_list/${currentCorrelationRecord.value.id}`
        ).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                milepostState.correlationData = []
                return
            }
            milepostState.allDemand = data.data.map(item => {
                return {
                    label: item.number,
                    value: item.requirementId
                }
            })
        })
    }
    //     用户故事部分=====================================================================================================================================================================================
    //     用户故事部分=====================================================================================================================================================================================
    //     用户故事部分=====================================================================================================================================================================================
    //     任务部分=====================================================================================================================================================================================
    //     任务部分=====================================================================================================================================================================================
    //     任务部分=====================================================================================================================================================================================
    const taskState = reactive({
        searchForm: {
            userName: taskLeader.value.name,
            keywords: undefined,
            storyId: undefined,
            directionField: 'default_sort-desc',
            taskStatus: undefined,
            taskType: undefined,
            endTimeList: [],
            storyLabels: undefined
        },
        expendAll: false,
        dataList: [],
        labelList: [],
        sortList: [
            {
                label: '默认',
                value: 'default_sort-desc'
            },
            {
                label: '创建时间正序',
                value: 'created_time-asc'
            },
            {
                label: '创建时间倒序',
                value: 'created_time-desc'
            },
            {
                label: '计划完成时间正序',
                value: 'end_time-asc'
            },
            {
                label: '计划完成时间倒序',
                value: 'end_time-desc'
            },
            {
                label: '计划开始时间正序',
                value: 'start_time-asc'
            },
            {
                label: '计划开始时间倒序',
                value: 'start_time-desc'
            },
            {
                label: '优先级正序',
                value: 'priority-asc'
            },
            {
                label: '优先级倒序',
                value: 'priority-desc'
            }
        ],
        treeData: [], // 原始树形数据
        questionTaskList: [], // 问题人物选择
        flatData: [], // 转换成 flat 的数组（只用于 Transfer 用 key）
        targetKeys: [], // 右边已选 key
        selectedKeys: [], // 左边当前选中 key
        SopTaskList: [],
        milepostList: [],
        addOrEditVisible: false,
        editTaskVisible: false,
        dataLoading: false,
        addOrEditTitle: '',
        modalForm: {
            selectKeys: [],
            taskList: [],
            functionAbbreviation: undefined,
            storyId: undefined,
            templateTaskId: []
        },
        storyList: [],
        current: 1,
        nextLoading: false,
        otherTaskVisible: false,
        otherTaskTitle: '',
        otherOkLoading: false,
        otherTaskForm: {
            taskList: [
                {
                    taskParticipantList: [],
                    allTile: [],
                    startTime: undefined,
                    endTime: undefined,
                    taskName: undefined,
                    workingHours: undefined,
                    taskOwner: taskLeader.value.name,
                    assessorName: taskLeader.value.name,
                    parentId: undefined,
                    storyId: undefined,
                    sopTaskList: []
                }
            ]
        },
        editTaskForm: {
            taskList: []
        },
        // 编辑子任务的时候的所属sop任务列表
        editSopTaskList: [],
        editTaskTitle: '',
        editTaskLoading: false,
        okLoading: false,
        //     所属SOP任务
        parentListMap: [],
        addOrEditQuestionVisible: false,
        questionLoading: false,
        addOrEditQuestionTitle: '',
        questionForm: {
            storyId: undefined,
            parentId: undefined,
            taskName: undefined,
            description: undefined,
            problemType: undefined,
            priority: undefined,
            version: undefined,
            startTime: undefined,
            endTime: undefined,
            taskParticipant: undefined
        },
        problemList: [],
        proityList: [],
        ppmTemplateCheckList: [],
        CompletionCheckListCheckList: [],
        okMbVisible: false,
        fileList: [],
        sopList: [],
        statusList: [],
        //     提测验收
        checkVisible: false,
        checkLoading: false,
        checkTitle: '',
        culaVisible: false,
        culaLoading: false,
        showCheck: false,
        keyNoteLoading: false,
        culaPeople: undefined,
        searchValue: ''
    })
    const taskFormRef = ref(null)
    const questionFormRef = ref(null)
    const rules = {
        storyId: [
            {
                required: true,
                message: '请选择用户故事名称',
                trigger: 'blur'
            }
        ],
        templateTaskId: [
            {
                required: true,
                message: '请选择SOP任务',
                trigger: 'blur'
            }
        ],
        allTime: [{ required: false, message: '请选择计划起止时间!', trigger: 'blur' }],
        functionAbbreviation: [{ required: false, message: '请输入功能简称', trigger: 'blur' }]
    }
    function handleResizeTaskColumn(w, col) {
        col.width = w
    }

    watch(
        () => taskState.otherTaskForm.taskList.map(item => item.storyId),
        (newList, oldList) => {
            newList.forEach((storyId, index) => {
                // 只有当 storyId 有值并且与旧值不一致时才触发
                if (storyId && storyId !== oldList?.[index]) {
                    taskState.otherTaskForm.taskList[index].parentId = undefined
                    get(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/get_sop_task/${storyId}`).then(
                        data => {
                            taskState.otherTaskForm.taskList[index].sopTaskList = data.data || []
                        }
                    )
                }
            })
        },
        { deep: true, immediate: false }
    )

    function getEditSopTask() {
        get(
            `/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/get_sop_task/${taskState.editTaskForm.taskList[0].storyId}`
        ).then(data => {
            taskState.editSopTaskList = data.data || []
        })
    }
    function getTaskLabelList() {
        get(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/story_labels/${useProjectId.value}`).then(
            data => {
                taskState.labelList = data.data
            }
        )
    }
    // 判断按钮是否可用的计算属性
    function isCirculationDisabledStory(item) {
        return !item.solverManagerPermission || item.taskStauts === '完成' || item.taskStauts === '延期完成'
    }
    // 开始按钮禁用状态
    function openDisabledStory(item) {
        if (item.taskStatus && item.taskStatus === '审批中') {
            return true
        }
        if (item.taskType === '问题') {
            // 问题由解决人开启，非解决人禁用
            if (!item.solverManagerPermission) {
                return true
            } else {
                return false
            }
        } else {
            // 其他类型问题由任务负责人开启
            if (!item.taskOwnerPermission) {
                return true
            } else {
                return false
            }
        }
    }
    //     编辑按钮禁用状态
    function disabledEditBtnStory(item) {
        if (item.taskStatus && item.taskStatus === '审批中') {
            return true
        }
        if (item.taskType === '问题') {
            // 问题由解决人开启，非解决人禁用
            if (!item.testManagerPermission) {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }
    //     新建问题禁用状态
    function addQuestionDisabled(item) {
        // return !item.testManagerPermission
        return false
    }

    //     提测禁用
    function testImprovementDisabled(item) {
        if (item.taskStatus && item.taskStatus === '审批中') {
            return true
        }
        if (!item.taskOwnerPermission || !item.examPassTime) {
            return true
        } else {
            return false
        }
    }
    //     验收禁用
    function checkDisabled(item) {
        if (item.taskStatus && item.taskStatus === '审批中') {
            return true
        }
        if (!item.testManagerPermission || !item.examPassTime) {
            return true
        } else {
            return false
        }
    }
    function handleExpendAll() {
        console.log(taskState.expendAll)
        if (taskState.expendAll) {
            taskState.expendAll = false
            taskState.dataList.forEach(item => {
                item.expend = false
            })
        } else {
            taskState.expendAll = true
            taskState.dataList.forEach(item => {
                item.expend = true
            })
        }
    }
    const validatePriority = (rule, value) => {
        if (value === undefined || value === null || value === '') {
            return Promise.reject(new Error('请输入优先级'))
        }
        const number = Number(value)
        const isValid = number > 0 && number < 100 && /^(\d{1,2})(\.\d)?$/.test(value.toString())
        return isValid ? Promise.resolve() : Promise.reject(new Error('请输入 1 到 99 之间，最多一位小数的正数'))
    }
    const currentmubanTask = ref({})
    // 新建SOP任务
    function handleAddSopTask() {
        if (!useProjectId.value) {
            message.info('请选择项目')
            return
        }
        currentmubanTask.value = {}
        taskState.addOrEditVisible = true
        taskState.addOrEditTitle = '新建SOP任务'
    }
    // 新建SOP任务快捷添加执行人
    function handlerAddPtMbPeopleTask(name, index) {
        if (taskState.modalForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
            taskState.modalForm.taskList[index].taskParticipantList = taskState.modalForm.taskList[
                index
            ].taskParticipantList.filter(item => item !== name)
        } else {
            taskState.modalForm.taskList[index].taskParticipantList.push(name)
        }
        getCurrentTaskParticipantList('modalForm', index)
    }
    function taskCancelStory() {
        taskState.addOrEditVisible = false
    }
    const currentOkTask = ref({})
    const currentOtherTask = ref({})
    function handleAddSonTask() {
        if (!useProjectId.value) {
            message.info('请选择项目')
            return
        }
        currentOtherTask.value = {}
        taskState.otherTaskVisible = true
        taskState.otherTaskForm = {
            taskList: [
                {
                    taskParticipantList: [],
                    allTile: [],
                    startTime: undefined,
                    endTime: undefined,
                    taskName: undefined,
                    workingHours: undefined,
                    taskOwner: taskLeader.value.name,
                    assessorName: taskLeader.value.name,
                    parentId: undefined,
                    storyId: undefined,
                    taskId: undefined,
                    description: undefined,
                    sopTaskList: []
                }
            ]
        }
        currentmubanTask.value = {}
        currentOtherTask.value = {}
        taskState.otherTaskTitle = '新建子任务'
    }
    const otherItem = {
        taskParticipantList: [],
        allTile: [],
        startTime: undefined,
        endTime: undefined,
        taskName: undefined,
        workingHours: undefined,
        taskOwner: taskLeader.value.name,
        assessorName: taskLeader.value.name,
        parentId: undefined,
        storyId: undefined,
        taskId: undefined,
        description: undefined
    }
    // 获取用户故事
    function getStory() {
        post('/solution-ppm/api/v2/built-in-system-ppm/project/story/search', {
            projectId: useProjectId.value
        }).then(data => {
            taskState.storyList = data.data.map(item => {
                return {
                    label: item.storyName,
                    value: item.id,
                    priority: item.priority
                }
            })
        })
    }
    function getPriorityByStory(storyId) {
        return taskState.storyList.find(item => item.value === storyId).priority || 'P3'
    }
    //     新建下一步获取任务
    function getTask() {
        taskFormRef.value.validate().then(() => {
            taskState.nextLoading = true
            post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/generate_task', {
                templateTaskId: taskState.modalForm.templateTaskId,
                storyId: taskState.modalForm.storyId,
                functionAbbreviation: taskState.modalForm.functionAbbreviation,
                projectId: useProjectId.value
            })
                .then(data => {
                    taskState.current = 2
                    taskState.modalForm.taskList = data.data.map(item => {
                        return {
                            ...item,
                            allTime: [item.startTime, item.endTime]
                        }
                    })
                })
                .finally(() => {
                    taskState.nextLoading = false
                })
        })
    }
    // 保存模板项目
    function confirmMbTask() {
        taskFormRef.value.validate().then(() => {
            taskState.okLoading = true
            taskState.modalForm.taskList.forEach(item => {
                item.startTime = item.allTime[0]
                item.endTime = item.allTime[1]
            })

            post(
                `/solution-ppm/api/v2/built-in-system-ppm/v2/platform/batch_add_template_task/${useProjectId.value}`,
                taskState.modalForm.taskList
            )
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success('创建成功，请及时关联月度目标，保证目标甘特图数据准确')

                    cancleMbTask()

                    getData()
                })
                .finally(() => {
                    taskState.okLoading = false
                })
        })
    }
    // 关闭模板任务新建
    function cancleMbTask() {
        taskState.addOrEditVisible = false
        taskState.current = 1
        taskState.modalForm.functionAbbreviation = undefined
        taskState.modalForm.templateTaskId = undefined
        taskState.modalForm = {
            templateTaskId: undefined,
            projectId: useProjectId.value,
            functionAbbreviation: undefined,
            taskList: []
        }
    }
    const PromiseProxy = Promise
    function handlerAddOtherPeople(name, index) {
        if (taskState.otherTaskForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
            taskState.otherTaskForm.taskList[index].taskParticipantList = taskState.otherTaskForm.taskList[
                index
            ].taskParticipantList.filter(item => item !== name)
        } else {
            taskState.otherTaskForm.taskList[index].taskParticipantList.push(name)
        }
        getCurrentTaskParticipantList('otherTaskForm', index)
    }
    function handlerAddEditPeople(name, index) {
        if (taskState.editTaskForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
            taskState.editTaskForm.taskList[index].taskParticipantList = taskState.editTaskForm.taskList[
                index
            ].taskParticipantList.filter(item => item !== name)
        } else {
            taskState.editTaskForm.taskList[index].taskParticipantList.push(name)
        }
        getCurrentTaskParticipantList('editTaskForm', index)
    }
    // 获取当前任务执行人
    function getCurrentTaskParticipantList(form, index) {
        let allPeople = []
        let people1 = taskState[form].taskList[index].taskParticipantList
        let people2 = taskState[form].taskList[index].taskOwner
        if (people1.length == 0 && !people2) {
            return
        }
        allPeople = [...people1, people2]
        allPeople = [...new Set(allPeople)]
        let dateList = taskState[form].taskList[index].allTime
        let days = 0

        // 计算天数
        if (dateList && dateList.length >= 2) {
            const startDate = new Date(dateList[0])
            const endDate = new Date(dateList[1])

            // 计算两个日期之间的天数差（包含起始日）
            const timeDiff = endDate.getTime() - startDate.getTime()
            days = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1
        }
        taskState[form].taskList[index].workingHours = allPeople.length * days * 8
        return allPeople.length * days * 8
    }
    function getStoryTaskParticipantList(form, index) {
        let allPeople = []
        let people1 = milepostState[form].taskList[index].taskParticipantList
        let people2 = milepostState[form].taskList[index].taskOwner
        if (people1.length == 0 && !people2) {
            return
        }
        allPeople = [...people1, people2]
        allPeople = [...new Set(allPeople)]
        let dateList = milepostState[form].taskList[index].allTime
        let days = 0

        // 计算天数
        if (dateList && dateList.length >= 2) {
            const startDate = new Date(dateList[0])
            const endDate = new Date(dateList[1])

            // 计算两个日期之间的天数差（包含起始日）
            const timeDiff = endDate.getTime() - startDate.getTime()
            days = Math.ceil(timeDiff / (1000 * 3600 * 24)) + 1
        }
        milepostState[form].taskList[index].workingHours = allPeople.length * days * 8
        return allPeople.length * days * 8
    }
    function handleAddOtherItem() {
        taskState.otherTaskForm.taskList.push({ ...otherItem })
    }
    const ptOtherRef = ref(null)
    // 保存其他任务
    function confirmOtherMb() {
        ptOtherRef.value.validate().then(() => {
            taskState.otherOkLoading = true

            //   新建
            taskState.otherTaskForm.taskList.forEach(item => {
                item.startTime = item.allTime[0]
                item.endTime = item.allTime[1]
            })
            post(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/child_task/${useProjectId.value}`, {
                dataList: taskState.otherTaskForm.taskList
            })
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success(data.message)
                    cancelOtherMb()
                    getData()
                })
                .finally(() => {
                    taskState.otherOkLoading = false
                })
        })
    }
    // 编辑任务保存
    function confirmEditOtherMb() {
        ptOtherRef.value.validate().then(() => {
            taskState.editTaskLoading = true
            taskState.editTaskForm.taskList.forEach(item => {
                item.startTime = item.allTime[0]
                item.endTime = item.allTime[1]
            })

            put(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task`, {
                ...taskState.editTaskForm.taskList[0],
                projectId: useProjectId.value
            })
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success('编辑成功')
                    getData()
                    currentOtherTask.value = {}
                    cancelEditTask()
                })
                .finally(() => {
                    taskState.editTaskLoading = false
                })
        })
    }
    // 关闭其他任务新建
    function cancelOtherMb() {
        taskState.otherTaskVisible = false
        taskState.otherTaskForm = {
            taskList: [
                {
                    taskParticipantList: [],
                    allTile: [],
                    startTime: undefined,
                    endTime: undefined,
                    taskName: undefined,
                    workingHours: undefined,
                    taskOwner: taskLeader.value.name,
                    assessorName: taskLeader.value.name,
                    parentId: undefined,
                    storyId: undefined,
                    taskId: undefined,
                    description: undefined,
                    sopTaskList: []
                }
            ]
        }
        currentmubanTask.value = {}
        currentOtherTask.value = {}
    }
    // 关闭修改
    function cancelEditTask() {
        taskState.editTaskVisible = false
        currentmubanTask.value = {}
        currentOtherTask.value = {}
        currentQuestion.value = {}
    }

    function handleDeleteOtherItem(index) {
        taskState.otherTaskForm.taskList.splice(index, 1)
    }
    async function handleEditTask(item) {
        if (item.taskStatus === '审批中') {
            message.info('审批中的任务不支持编辑')
            return
        }
        const record = cloneDeep(item)
        if (item.taskType === 'SOP任务' || item.taskType === '子任务') {
            if (item.taskType === 'SOP任务') {
                currentmubanTask.value = record
            } else if (item.taskType === '子任务') {
                currentOtherTask.value = record
            }
            taskState.editTaskForm.taskList[0] = {
                ...item,
                parentId: record.parentId === 0 ? undefined : record.parentId, // 显式赋值
                examPassTime: record.examPassTime || undefined
            }
            taskState.editTaskForm.taskList[0].allTime = [record.startTime, record.endTime]
            getStory()
            // if (item.taskType === '子任务') {
            //
            // }
            getEditSopTask()
            taskState.editTaskForm.taskList[0].examPassTime = record.examPassTime || undefined
            taskState.editTaskVisible = true
            taskState.editTaskTitle = `编辑${item.taskType}`
        } else {
            currentQuestion.value = record
            taskState.addOrEditQuestionVisible = true
            taskState.addOrEditQuestionTitle = '编辑问题任务'
            Object.assign(taskState.questionForm, record)
            await getStory()
            await getQuestionTask()
            nextTick(() => {
                let descriptionData = JSON.parse(record.description)
                taskQuillEditor.value.setContents(descriptionData)
            })
        }
    }
    const currentQuestion = ref({})
    //     父工单提交表单
    function questionSubmit() {
        questionFormRef.value.validate().then(async () => {
            taskState.questionLoading = true
            const deltaContent = taskQuillEditor.value.getContents()

            const imageUploadPromises = []

            deltaContent.ops.forEach(op => {
                if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                    const localSrc = op.insert.image

                    // 如果是 base64 图片，上传并替换为 URL
                    const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                    const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                        // 替换 op 中的 base64 URL 为服务器返回的 URL
                        op.insert.image = fullUrl
                    })

                    imageUploadPromises.push(uploadPromise)
                }
            })
            try {
                await Promise.all(imageUploadPromises)
                if (currentQuestion.value.taskId) {
                    // 编辑保存逻辑
                    const params = { ...taskState.questionForm }
                    params.description = JSON.stringify(deltaContent)
                    put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/problem', {
                        projectId: useProjectId.value,
                        ...params
                    })
                        .then(data => {
                            if (data.code !== 200) {
                                message.error(data.message)
                                return
                            }
                            message.success(data.message)
                            taskState.addOrEditVisible = false
                            resetQuestion()
                            getData()
                        })
                        .finally(() => {
                            taskState.questionLoading = false
                        })
                } else {
                    // 新建保存逻辑
                    const params = { ...taskState.questionForm }
                    params.description = JSON.stringify(deltaContent)
                    post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/problem', {
                        projectId: useProjectId.value,
                        ...params
                    })
                        .then(data => {
                            if (data.code !== 200) {
                                message.error(data.message)
                                return
                            }
                            message.success(data.message)
                            taskState.addOrEditVisible = false
                            resetQuestion()
                            getData()
                        })
                        .finally(() => {
                            taskState.questionLoading = false
                        })
                }
            } catch (error) {
                taskState.questionLoading = false
                console.error('图片上传失败', error)
                return // 终止提交
            }
        })
    }
    const taskQuillEditor = ref(null)
    function resetQuestion() {
        taskState.addOrEditQuestionVisible = false
        taskState.questionForm = {
            storyId: undefined,
            parentId: undefined,
            taskName: undefined,
            description: undefined,
            problemType: undefined,
            priority: undefined,
            version: undefined,
            startTime: undefined,
            endTime: undefined,
            taskParticipant: undefined
        }
        currentQuestion.value = {}
    }
    function handleAddQuestion(record) {
        const item = cloneDeep(record)
        taskState.addOrEditQuestionTitle = '新建问题'
        taskState.questionForm.storyId = item.storyId
        taskState.questionForm.parentId = item.taskId
        getStory()
        getQuestionTask()
        getQuestionType()
        getGroupPeople()
        taskState.addOrEditQuestionVisible = true
        nextTick(() => {
            initTitle()
            taskQuillEditor.value.setContents('')
        })
    }
    //     获取问题任务
    function getQuestionTask() {
        post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/list', {
            'projectId': useProjectId.value
        }).then(data => {
            taskState.questionTaskList = data.data
        })
    }
    const groupList = ref([])
    //     获取用户组成员
    function getGroupPeople() {
        get('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser').then(({ data }) => {
            groupList.value = data.userDtoList.map(item => {
                return {
                    label: item.name,
                    value: item.name
                }
            })
        })
    }
    function getQuestionType() {
        get(' /solution-ppm-basic-data/api/v1/dictionary/search/PTRW.WTLX').then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            taskState.problemList = data.data.map(item => {
                return {
                    label: item.itemName,
                    value: item.itemCode
                }
            })
        })
    }
    function getProity() {
        get(' /solution-ppm-basic-data/api/v1/dictionary/search/PTRW.YXJ').then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            taskState.proityList = data.data.map(item => {
                return {
                    label: item.itemName,
                    value: item.itemCode
                }
            })
        })
    }

    //     任务开始
    function handleOpen(record) {
        record.startLoading = true
        if (record.instanceId) {
            message.info('请审批完成后再开始任务')
            return
        }
        if (record.taskType === '问题') {
            put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
                'id': record.taskId,
                'status': '开始',
                'solver': ''
            })
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success(data.message)
                    getData()
                })
                .finally(() => {
                    record.startLoading = false
                })
        } else {
            put(`/solution-ppm/api/v2/built-in-system-ppm/refactoring_task/start_task/${record.taskId}`)
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success(data.message)
                    getData()
                })
                .finally(() => {
                    record.startLoading = false
                })
        }
    }
    //     任务完成
    function beforeOkMb(record) {
        if (record.taskStatus === '测试中') {
            message.info('请联系测试经理发起验收后再试')
            return
        }
        if (record.taskType === '问题') {
            if (record.taskStatus === '审批中' || record.taskStatus === '延期完成' || record.taskStatus === '完成') {
                message.error(`问题状态为${record.taskStatus}的任务无法进行完成操作`)
                return
            }
            templateOkDisabled.value = true
            put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
                'id': record.taskId,
                'status': '完成',
                'solver': ''
            })
                .then(data => {
                    if (data.code !== 200) {
                        message.error(data.message)
                        return
                    }
                    message.success(data.message)
                    getData()
                })
                .finally(() => {
                    templateOkDisabled.value = false
                })
        } else {
            if (record.taskStatus === '审批中' || record.taskStatus === '延期完成' || record.taskStatus === '完成') {
                message.error(`问题状态为${record.taskStatus}的任务无法进行完成操作`)
                return
            }
            // 任务的完成
            if (record.taskType === 'SOP任务' || record.taskType === '子任务') {
                currentOkTask.value = record
                // 新-获取审核标准赋值
                get(
                    `/solution-ppm/api/v2/built-in-system-ppm/v2/platform/${currentOkTask.value.taskId}/assessor_standard_and_sop/search`
                ).then(data => {
                    taskState.ppmTemplateCheckList =
                        data.data.assessorStandardList?.map(item => {
                            return {
                                type: item.type,
                                selected: item.selected,
                                content: item.content
                            }
                        }) || []
                    taskState.sopList = data.data.sopList
                    if (data.data.finishStandard !== null) {
                        taskState.CompletionCheckListCheckList = data.data.finishStandardList
                    } else {
                        taskState.CompletionCheckListCheckList = []
                    }
                    get(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/attachment/${record.taskId}`).then(
                        ({ data }) => {
                            taskState.fileList = data?.attachment ? JSON.parse(data.attachment) : []
                            taskState.okMbVisible = true
                            finishTimeSubmit.value = dayjs().format('YYYY-MM-DD')
                        }
                    )
                })
            } else {
                //     问题的完成
            }
        }
    }
    // 任务恢复
    function confirmRecoverTask(record) {
        put(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change`, {
            status: '任务恢复',
            id: record.taskId
        }).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            message.success(data.message)
            getData()
        })
    }
    //     展示附件
    const fileShowList = ref([])
    const showFileVisible = ref(false)
    function showMore(data) {
        fileShowList.value = data
        showFileVisible.value = true
    }
    function showFileCancel() {
        fileShowList.value = []
        showFileVisible.value = false
    }
    // 模板项目附件模板下载
    function handlerDownload(item) {
        fetch(item.url)
            .then(response => response.blob())
            .then(blob => {
                const downloadLink = document.createElement('a')
                const url = URL.createObjectURL(blob)
                downloadLink.href = url
                downloadLink.setAttribute('download', item.name)
                downloadLink.style.display = 'none'
                document.body.appendChild(downloadLink)
                downloadLink.click()
                document.body.removeChild(downloadLink)

                // Release the object URL after the download
                URL.revokeObjectURL(url)
            })
            .catch(err => {
                console.error('Download failed', err)
            })
    }
    // 图片预览

    const stateF = reactive({
        previewVisible: false,
        previewImage: '',
        previewFileUrl: '',
        isImagePreview: false
    })
    function previewAttachment(item) {
        // 检查附件类型
        if (item.type.startsWith('image')) {
            stateF.isImagePreview = true
            stateF.previewImage = item.url // 设置预览图片的URL
            stateF.previewVisible = true // 显示模态框
        } else {
            // stateF.isImagePreview = false;
            // // 如果是其他类型的文件，直接在模态框中显示
            // stateF.previewFileUrl = item.url; // 设置预览文件的URL
            message.info('目前仅支持图片预览')
        }
    }
    // 任务下载全部模板
    function downLoadTemplate() {
        if (currentOkTask.value.attachmentTemplateList.length < 1) {
            message.info('任务没有附件')
        } else {
            post(
                `/solution-ppm/api/v2/built-in-system-ppm/delivery_task/download_template/${currentOkTask.value.taskId}`,
                null,
                { responseType: 'arraybuffer' }
            ).then(res => {
                downloadZip(res, '任务附件模板.zip')
            })
        }
    }
    function downloadZip(response, name) {
        const blob = new Blob([response], { type: 'application/zip;charset=utf-8' })
        const downloadElement = document.createElement('a')
        const href = window.URL.createObjectURL(blob)
        downloadElement.href = href
        downloadElement.download = name // 下载后文件名
        document.body.appendChild(downloadElement)
        downloadElement.click()
        document.body.removeChild(downloadElement)
        window.URL.revokeObjectURL(href)
        return href
    }
    const uploadLoading = ref(false)
    function handlerUploadWc(file) {
        uploadLoading.value = true
        const data = new FormData()
        data.append('file', file)

        post('/file-storage/api/v1/file/upload', data)
            .then(({ data: { fullUrl } }) => {
                if (data) {
                    taskState.fileList = [
                        ...taskState.fileList,
                        {
                            uid: file.uid,
                            lastModified: file.lastModified,
                            name: file.name,
                            size: file.size,
                            type: file.type,
                            status: 'done',
                            url: fullUrl
                        }
                    ]
                }
            })
            .finally(() => {
                uploadLoading.value = false
            })
        return false
    }

    function handleRemoveWc(file) {
        taskState.fileList = taskState.fileList.filter(item => item.uid !== file.uid)
    }
    // 暂存sop
    function handleSubmitSop() {
        const params = {
            form: [],
            sopList: taskState.sopList,
            taskId: currentOkTask.value.taskId
        }
        params.form = [...taskState.CompletionCheckListCheckList, ...taskState.ppmTemplateCheckList]
        post('/solution-ppm/api/v2/built-in-system-ppm/delivery_task/save_standard_sop', params).then(() => {
            message.success('操作成功')
            taskState.okMbVisible = false
            getData()
        })
    }
    // 新-新模板项目检查清单确认事件
    const templateOkDisabled = ref(false)
    function handlerTemplateOk() {
        if (!checkAllSelected(taskState.sopList[0].contentList)) {
            message.info('请确认完成标准及SOP全部已实现')
        } else {
            handlerCheckOk()
        }
    }
    function checkAllSelected(content) {
        for (let i = 0; i < content.length; i++) {
            if (!content[i].selected) {
                return false // 只要有一个 selected 不为 true，就返回 false
            }
        }
        return true // 如果所有的 selected 都为 true，返回 true
    }
    const finishTimeSubmit = ref()
    function handlerCheckOk() {
        templateOkDisabled.value = true
        const params = {
            form: [],
            sopList: taskState.sopList,
            taskId: currentOkTask.value.taskId
        }
        params.form = [...taskState.CompletionCheckListCheckList, ...taskState.ppmTemplateCheckList]
        post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/attachment', {
            ppmEnclosureInfoList: taskState.fileList,
            taskId: currentOkTask.value.taskId
        }).then(data => {
            if (data.code === 200) {
                post('/solution-ppm/api/v2/built-in-system-ppm/delivery_task/save_standard_sop', params).then(() => {
                    if (data.code === 200) {
                        put('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/status', {
                            taskId: currentOkTask.value.taskId,
                            actualFinishTime: finishTimeSubmit.value
                        })
                            .then(data => {
                                if (data.code !== 200) {
                                    message.error(data.message)
                                    templateOkDisabled.value = false
                                    return
                                }
                                templateOkDisabled.value = false
                                taskState.okMbVisible = false
                                message.success('操作成功')
                                getData()
                            })
                            .finally(() => {
                                templateOkDisabled.value = false
                            })
                    } else {
                        message.error('提交失败')
                        templateOkDisabled.value = false
                    }
                })
            } else {
                templateOkDisabled.value = false
                message.error('附件上传失败')
            }
        })
    }
    function confirmDeleteQuestion(record) {
        if (record.taskFinishTime) {
            message.info('已完成的任务不支持删除')
            return
        } else if (record.taskStatus === '审批中') {
            message.info('审批中的任务不支持删除')
            return
        }
        del(` /solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/problem/${record.taskId}`).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            message.success(data.message)
            getData()
        })
    }
    function confirmDeleteTask(record) {
        if (record.taskFinishTime) {
            message.info('已完成的任务不支持删除')
            return
        } else if (record.taskStatus === '审批中') {
            message.info('审批中的任务不支持删除')
            return
        }
        del('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/approve', {
            data: {
                plName: record.plName,
                taskId: record.taskId
            }
        }).then(({ code, message: errorMsg }) => {
            if (code === 200) {
                message.success('提交成功')
                getData()
            } else {
                message.error(errorMsg || '删除失败')
            }
        })
    }
    //     提测验收
    const currentCheckData = ref({})
    const checkFlag = ref('')
    function handleCheck(item, flag) {
        currentCheckData.value = item
        checkFlag.value = flag
        taskState.checkVisible = true
        taskState.checkTitle = `确认${flag}`
    }
    const currentCirculationData = ref({})
    // 流转
    function showCirculation(record, flag) {
        currentCirculationData.value = record
        taskState.culaVisible = true
    }
    function handleSubmitCirculation() {
        taskState.culaLoading = true
        put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
            id: currentCirculationData.value.taskId,
            status: '流转',
            solver: taskState.culaPeople
        })
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                message.success(data.message)
                cancelCirculation()
                getData()
            })
            .finally(() => {
                taskState.culaLoading = false
            })
    }
    function cancelCirculation() {
        taskState.culaPeople = undefined
        taskState.culaVisible = false
        currentCirculationData.value = {}
    }
    function handleSubmitCheck() {
        taskState.checkLoading = true
        put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
            id: currentCheckData.value.taskId,
            status: checkFlag.value === '提测' ? '测试中' : '验收中'
        })
            .then(data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                message.success(data.message)
                cancelCheck()
                getData()
            })
            .finally(() => {
                taskState.checkLoading = false
            })
    }
    function cancelCheck() {
        taskState.checkVisible = false
        currentCheckData.value = {}
        checkFlag.value = ''
    }
    // 模板项目-风险预警
    const warnState = reactive({
        warringVisible: false,
        templateRisk: {
            taskId: undefined,
            taskName: undefined,
            riskDescription: undefined,
            milepostId: undefined,
            projectId: undefined,
            solution: undefined
        }
    })
    function handlerWarning(record) {
        if (!record.taskOwnerPermission) {
            message.error('非该任务任务负责人')
        } else {
            if (record.taskFinishTime !== null) {
                message.info('该任务已完成，此功能已关闭')
            } else {
                get(`/solution-ppm/api/v2/built-in-system-ppm/permission/ppyj/create`).then(({ data }) => {
                    if (data === false) {
                        message.info('暂无权限')
                    } else {
                        warnState.warringVisible = true
                        warnState.templateRisk.taskName = record.taskName
                        warnState.templateRisk.riskDescription = record.riskDescription
                        warnState.templateRisk.solution = record.solution
                        warnState.templateRisk.taskId = record.taskId
                        warnState.templateRisk.projectId = record.projectId
                        warnState.templateRisk.milepostId = record.milepostId
                    }
                })
            }
        }
    }
    const templateRiskRef = ref(null)
    // 模板项目风险保存
    function handleTemplateRiskOk() {
        templateRiskRef.value.validate().then(() => {
            const params = {
                taskId: warnState.templateRisk.taskId,
                projectId: warnState.templateRisk.projectId,
                milepostId: warnState.templateRisk.milepostId,
                riskDescription: warnState.templateRisk.riskDescription,
                solution: warnState.templateRisk.solution
            }
            post('/solution-ppm/api/v2/built-in-system-ppm/refactoring_task/task_warn', params).then(data => {
                if (data.code === 200) {
                    message.success('操作成功')
                    warnState.warringVisible = false
                    getData()
                } else {
                    message.error(data.message)
                }
            })
        })
    }
    // 备注
    const noteState = reactive({
        visibleNotes: false,
        noteData: [],
        notesColumns: [
            { title: '备注内容', ellipsis: true, dataIndex: 'description', align: 'center' },
            { title: '提交人', dataIndex: 'submitter', align: 'center', width: '200px' },
            { title: '提交时间', dataIndex: 'submissionTime', align: 'center', width: '200px' },
            { title: '操作', dataIndex: 'operation', align: 'center', width: '150px' }
        ]
    })
    function handlerShowNotes(record) {
        editRemarkData.value = cloneDeep(record)
        post('/solution-ppm/api/v2/built-in-system-ppm/description/search', {
            sourceId: record.taskType ? record.taskId : record.id,
            descriptionType: record.taskType ? 'TASK' : 'STORY'
        }).then(({ data }) => {
            noteState.noteData = data
            console.log(noteState.noteData)
            noteState.visibleNotes = true
        })
    }
    // 🧩 新增：封装一个刷新函数
    function refreshNotes() {
        if (!editRemarkData.value) return
        post('/solution-ppm/api/v2/built-in-system-ppm/description/search', {
            sourceId: editRemarkData.value.taskType ? editRemarkData.value.taskId : editRemarkData.value.id,
            descriptionType: editRemarkData.value.taskType ? 'TASK' : 'STORY'
        }).then(({ data }) => {
            noteState.noteData = data
        })
    }

    const editRemarkData = ref({})
    const currentRowRemark = ref({}) // 存编辑前快照
    // 保存
    // const handleSaveRemark = record => {
    //     console.log(record, 'saverecord')
    //     if (!record.description) {
    //         message.info('请输入备注内容')
    //         return
    //     }
    //     record.okBtnLoading = true
    //     const api = record.isNew ? post : put
    //     const { submissionTime, ...oldDate } = currentRowRemark.value
    //     let params = {}
    //     if (record.isNew) {
    //         params = {
    //             description: record.description,
    //             sourceId: editRemarkData.value.taskType ? editRemarkData.value.taskId : editRemarkData.value.id,
    //             descriptionType: editRemarkData.value.taskType ? 'TASK' : 'STORY'
    //         }
    //     } else {
    //         params = {
    //             description: record.description,
    //             sourceId: editRemarkData.value.taskType ? editRemarkData.value.taskId : editRemarkData.value.id,
    //             descriptionType: editRemarkData.value.taskType ? 'TASK' : 'STORY',
    //             ...currentRowRemark.value
    //         }
    //     }
    //     api('/solution-ppm/api/v2/built-in-system-ppm/description', params)
    //         .then(data => {
    //             if (data.code !== 200) {
    //                 message.error(data.message)
    //                 return
    //             }
    //             message.success(data.message)
    //
    //             if (record.isNew) {
    //                 // 新建数据的情况
    //                 const index = noteState.noteData.findIndex(item => item === record)
    //                 if (index !== -1) {
    //                     // 用后端返回的数据替换临时数据
    //                     noteState.noteData.splice(index, 1, {
    //                         ...data.data,
    //                         editing: false
    //                     })
    //                 }
    //             } else {
    //                 // 编辑现有数据的情况
    //                 Object.assign(record, data.data, { editing: false })
    //             }
    //             record.editing = false
    //         })
    //         .finally(() => {
    //             record.okBtnLoading = false
    //         })
    // }
    // helper: 精确定位一行在 noteData 的 index
    function findRowIndex(record) {
        if (!record) return -1
        // 优先使用后端 id
        if (record.descriptionId !== undefined && record.descriptionId !== null) {
            const idx = noteState.noteData.findIndex(item => item.descriptionId === record.descriptionId)
            if (idx !== -1) return idx
        }
        // 然后使用临时 id（新建使用）
        if (record.tempId !== undefined) {
            const idx = noteState.noteData.findIndex(item => item.tempId === record.tempId)
            if (idx !== -1) return idx
        }
        // 回退到对象引用（最稳）
        const idx = noteState.noteData.indexOf(record)
        return idx
    }
    // 新建历史备注
    // 新建一行（带 tempId）
    function handleAddRemark() {
        noteState.noteData.unshift({
            tempId: Date.now() + Math.random(), // 确保唯一
            description: '',
            editing: true,
            isNew: true,
            okBtnLoading: false
        })
    }

    // 保存（新建/编辑）——稳健实现
    const handleSaveRemark = async record => {
        if (!record.description || !record.description.trim()) {
            message.warning('请输入备注内容')
            return
        }

        // 防重入
        if (record.okBtnLoading) return
        record.okBtnLoading = true

        try {
            const api = record.isNew ? post : put

            // 只组装需要的参数（不要带 UI 字段）
            const params = {
                description: record.description,
                sourceId: editRemarkData.value.taskType ? editRemarkData.value.taskId : editRemarkData.value.id,
                descriptionType: editRemarkData.value.taskType ? 'TASK' : 'STORY'
            }

            if (!record.isNew) {
                // 把 record 中后端需要的字段追加进 params（但排除 UI 字段）
                const { editing, okBtnLoading, isNew, tempId, ...rest } = record
                Object.assign(params, rest)
            }

            const res = await api('/solution-ppm/api/v2/built-in-system-ppm/description', params)

            if (res.code !== 200) {
                message.error(res.message || '保存失败')
                return
            }

            message.success(res.message || '保存成功')

            // 先尝试精确替换本地行（优先 descriptionId/tempId）
            const targetIndex = findRowIndex(record)
            if (targetIndex !== -1) {
                // 用后端返回的数据替换该行（保证没有 UI 字段污染）
                noteState.noteData.splice(targetIndex, 1, {
                    ...res.data,
                    editing: false,
                    isNew: false,
                    okBtnLoading: false
                })
            } else {
                // 万一找不到（极端情况），把返回数据放到顶部
                noteState.noteData.unshift({ ...res.data, editing: false, isNew: false, okBtnLoading: false })
            }

            // 最后强制刷新以保证数据一致（可选，但推荐，防止并发导致的脏数据）
            await refreshNotes()
        } catch (err) {
            console.error(err)
            message.error('保存异常')
        } finally {
            record.okBtnLoading = false
        }
    }

    function cancelNotice() {
        noteState.noteData = []
        editRemarkData.value = {}
        currentRowRemark.value = {}
        noteState.visibleNotes = false
        getData()
    }
    // 编辑
    const handleEditRemark = record => {
        currentRowRemark.value = cloneDeep(record)
        record.editing = true
    }

    // 取消
    // 取消：如果新建则删除行；否则恢复快照
    function handleCancelRemark(record, index) {
        if (record.isNew) {
            // 用 index 优先删除（传参 index 更可靠）
            if (index !== undefined && index > -1) {
                noteState.noteData.splice(index, 1)
            } else {
                const idx = findRowIndex(record)
                if (idx !== -1) noteState.noteData.splice(idx, 1)
            }
            return
        }
        // 恢复快照
        if (currentRowRemark.value && currentRowRemark.value.descriptionId === record.descriptionId) {
            Object.assign(record, currentRowRemark.value)
        } else {
            // 如果快照丢了，确保关闭编辑状态
            record.editing = false
        }
    }

    // 删除
    // 删除也走刷新流程
    function handleDeleteRemark(id, index) {
        del(`/solution-ppm/api/v2/built-in-system-ppm/description/${id}`).then(res => {
            if (res.code !== 200) {
                message.error(res.message || '删除失败')
                return
            }
            message.success(res.message || '删除成功')
            // 最稳做法：刷新整表
            refreshNotes()
        })
    }
    //     审批记录以及更换状态
    const statuState = reactive({
        visible: false,
        list: [],
        taskType: undefined,
        taksName: undefined
    })
    function getTaskStatus(id, type, mileId, status, taskType, item) {
        statuState.taskType = taskType
        statuState.taskName = item.taskName
        get(`/solution-ppm/api/v2/built-in-system-ppm/refactoring_task/task_approval_detail/${id}/${type}    `).then(
            data => {
                if (data.code !== 200) {
                    message.error(data.message)
                    return
                }
                statuState.visible = true
                if (mileId) {
                    get(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/get_template_task_status/${mileId}`).then(
                        data2 => {
                            if (data2.code !== 200) {
                                message.error(data2.message)
                                return
                            }
                            statusList.value = data2.data
                        }
                    )
                }
                statusList.value = []
                statusCurrentId.value = id
                statusCheckList.value = status
                statuState.list = data.data
                statusRadio.value = '状态变更'
            }
        )
    }

    const statusCurrentId = ref(null)
    const statusRadio = ref('状态变更')
    const statusList = ref([])
    const statusCheckList = ref('')
    function handleConfirmStatus() {
        if (statuState.taskType === '问题') {
            message.info('问题不支持自定义状态')
            return
        }
        put(
            ` /solution-ppm/api/v2/built-in-system-ppm/v2/platform/modify_task_status/${statusCurrentId.value}/${statusCheckList.value}`
        ).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                return
            }
            message.success(data.message)
            statuState.visible = false
            statusRadio.value = '状态变更'
            getData()
        })
    }

    // 判断按钮是否可用的计算属性
    function isCirculationDisabled(item) {
        return !item.solverManagerPermission || item.taskStauts === '完成' || item.taskStauts === '延期完成'
    }
    // 开始按钮禁用状态
    function openDisabled(item) {
        if (item.taskStatus && item.taskStatus === '审批中') {
            return true
        }
        if (item.taskType === '问题') {
            // 问题由解决人开启，非解决人禁用
            if (!item.solverManagerPermission) {
                return true
            } else {
                return false
            }
        } else {
            // 其他类型问题由任务负责人开启
            if (!item.taskOwnerPermission) {
                return true
            } else {
                return false
            }
        }
    }
    //     编辑按钮禁用状态
    function disabledEditBtn(item) {
        if (item.taskStatus && item.taskStatus === '审批中') {
            return true
        }
        if (item.taskType === '问题') {
            // 问题由解决人开启，非解决人禁用
            if (!item.testManagerPermission) {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }

    //完成按钮禁用 TODO:补充非开发和开发
    function disabledComplate(item) {
        if ((item.taskStatus && item.taskStatus === '审批中') || item.taskFinishTime) {
            return true
        }
        if (item.taskType === '问题') {
            if (!item.testManagerPermission) {
                return true
            } else {
                return false
            }
        } else {
            // 如果任务目前是提测和验收状态就是产品经理点完成。否则是任务任务负责人
            if (item.taskStatus === '验收中' || item.taskStatus === '测试中') {
                if (!item.productManagerPermission) {
                    return true
                } else {
                    return false
                }
            } else {
                if (!item.taskOwnerPermission) {
                    return true
                } else {
                    return false
                }
            }
        }
    }
    // 恢复
    //完成按钮禁用 TODO:补充非开发和开发
    function disabledRestore(item) {
        if ((item.taskStatus && item.taskStatus === '审批中') || !item.taskOwnerPermission) {
            return true
        }
        return false
    }

    //     关键路径改

    const modifiedKeynotes = reactive(new Map()) // key: taskId, value: '是' or '否'
    const initialKeynotes = new Map()

    const getIconStatus = status => {
        if (status === 'finish') {
            return 'finish'
        } else if (status === 'process') {
            return 'process'
        } else {
            return 'error'
        }
    }

    const showMsgState = reactive({
        visible: false,
        msg: undefined,
        title: ''
    })

    function getBgc(type) {
        if (type === 'P0') {
            return '#FF4D4F'
        } else if (type === 'P1') {
            return '#FF7A45'
        } else if (type === 'P2') {
            return '#FFA940'
        } else if (type === 'P3') {
            return '#FFC53D'
        }
    }
    const typeColorMap = {
        'SOP任务': '#FF85C0',
        '子任务': '#FF85C0',
        '问题': '#FF85C0'
    }
    function getStatusColor(status) {
        return colorMap[status] || '#9DBAFF'
    }
    function getTypeColor(status) {
        return typeColorMap[status] || '#3875ff'
    }
    const classMap = {
        '问题': 'question-task-bg',
        '子任务': 'son-task-bg',
        'SOP任务': 'sop-task-bg'
    }
    const colorMap = {
        '进行中': '#3875FF',
        '审批中': '#1890FF',
        '未启动': '#BBBBBB',
        '完成': '#52C41A',
        '延期完成': '#FA8C16',
        '测试中': '#A0D911',
        '延期': '#FA3D16',
        '提测': '#A0D911',
        '验收': '#9254DE'
    }
    //     任务部分==================================================================================================
    //     任务部分=============================================================================================
    //     任务部分=========================================================================================
    // 格式化函数
    function formatPercentage(value) {
        if (value === 0) return '0'
        return value.toFixed(2)
    }
    //     点击用户故事/任务显示概览
    const descriptionState = reactive({
        visible: false,
        title: undefined,
        type: undefined,
        description: {}
    })
    function showDescription(data, type) {
        descriptionState.description = cloneDeep(data)
        if (type === '任务') {
            descriptionState.description.iterationVersionName = data
        }
        descriptionState.type = type
        descriptionState.title = type == '任务' ? '任务概览' : '用户故事概览'
        descriptionState.visible = true
        console.log(descriptionState.visible)
    }
    function cancelDescription() {
        descriptionState.visible = false
        descriptionState.description = {}
        descriptionState.type = undefined
        descriptionState.title = undefined
    }
    // 判断是否已全部展开
    const isAllExpanded = computed(() => state.expandedRowKeys.length === state.dataSource.length)
    const expendSping = ref(false)
    // 切换展开/收起全部
    const toggleExpandAll = () => {
        expendSping.value = true
        if (isAllExpanded.value) {
            state.expandedRowKeys = [] // 收起
        } else {
            state.expandedRowKeys = state.dataSource.map(item => item.id) // 全部展开
        }
        expendSping.value = false
    }
    const changeLogState = reactive({
        visible: false,
        dataSource: []
    })
    const changeLogColumns = ref([
        {
            dataIndex: 'classify',
            title: '变更模块',
            ellipsis: true,
            align: 'center',
            width: 100,
            resizable: true,
            fixed: 'left'
        },

        {
            dataIndex: 'changeFieldName',
            title: '变更字段名',
            ellipsis: true,
            align: 'center',
            width: 180,
            resizable: true,
            fixed: 'left'
        },
        {
            dataIndex: 'beforeChange',
            title: '变更前（字段名称+数据）',
            ellipsis: true,
            align: 'center',
            width: 300,
            resizable: true
        },
        {
            dataIndex: 'afterChange',
            title: '变更后（字段名称+数据）',
            ellipsis: true,
            align: 'center',
            width: 300,
            resizable: true
        },
        {
            dataIndex: 'submitter',
            title: '提交人',
            align: 'center',
            ellipsis: true,
            width: 100
        },
        {
            dataIndex: 'submissionTime',
            title: '提交时间',
            align: 'center',
            ellipsis: true,
            width: 200
        }
    ])
    function showChangeLog(record) {
        post('/solution-ppm/api/v2/built-in-system-ppm/changeRecord/list', {
            storyId: record.id,
            projectId: useProjectId.value,
            taskId: record.taskId
        }).then(data => {
            if (data.code !== 200) {
                message.error(data.message)
                state.dataSource = []
                return
            }
            changeLogState.dataSource = data.data.dataList
            changeLogState.visible = true
        })
    }
    function cancelChangeLog() {
        changeLogState.visible = false
        changeLogState.dataSource = []
    }
    // ⚙️ 格式化所有编号（用于 tooltip 展示）
    const normalizeToArray = v => {
        if (v == null) return []
        if (Array.isArray(v)) return v.map(i => (i == null ? '' : String(i).trim()))
        return String(v)
            .split(/[,;；]/)
            .map(i => i.trim())
    }

    const cleanArray = arr => arr.filter(i => i && i !== 'null' && i !== 'undefined')

    const formatAllCodes = ids => {
        const arr = cleanArray(normalizeToArray(ids))
        if (!arr.length) return ''
        arr.sort()
        return arr.join('；')
    }

    const formatFirstCode = ids => {
        const arr = cleanArray(normalizeToArray(ids))
        if (!arr.length) return ''
        arr.sort()
        return arr.length === 1 ? arr[0] : `${arr[0]}...`
    }

    const formatAllLabels = labels => {
        const arr = cleanArray(normalizeToArray(labels))
        if (!arr.length) return ''
        arr.sort()
        return arr.join('；')
    }

    // 返回用于渲染的数组（**始终返回数组**）
    const formatShowLabels = labels => {
        const arr = cleanArray(normalizeToArray(labels))
        if (!arr.length) return []
        arr.sort()
        if (arr.length > 2) return [arr[0], `${arr[1]}...`]
        return arr
    }

    // ---------- 更严格的存在判断（避免空字符串导致的 children 为空） ----------
    const hasLabels = record => {
        try {
            return formatShowLabels(record?.labels).length > 0
        } catch (e) {
            return false
        }
    }
    const hasNumberList = record => {
        try {
            return cleanArray(normalizeToArray(record?.numberList)).length > 0
        } catch (e) {
            return false
        }
    }
</script>
<style lang="less" scoped>
    .page_root {
        width: 100%;
        height: 100%;
        overflow: auto;
    }
    .page_root :deep(.@{ant-prefix}-spin-nested-loading),
    .page_root :deep(.@{ant-prefix}-spin-container) {
        height: 100%;
    }
    .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper) {
        display: flex;
        flex-flow: column nowrap;
        justify-content: flex-start;
    }
    .page_root :deep(.@{ant-prefix}-table) {
        flex: auto;
        overflow: auto;
    }
    .table-moreBtn_down {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        width: 100px;
    }

    .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
        background: #ebf1ff;
    }

    /*  表格树结构样式处理，展开按钮层级增加*/
    :deep(.@{ant-prefix}-table-row-expand-icon) {
        z-index: 1;
    }
    /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
    :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 15px !important;
        width: calc(100% - 15px);
    }
    :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 30px !important;
        width: calc(100% - 30px);
    }
    :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 45px !important;
        width: calc(100% - 45px);
    }
    :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
        left: 60px !important;
        width: calc(100% - 60px);
    }

    /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
    :deep(.@{ant-prefix}-transfer-list) {
        height: 100%;
        width: 50%;
    }
    /*样式*/
    .body {
        height: 100%;
        background-color: #fff;
        overflow: hidden;
        padding: 10px;
    }
    .top-search :deep(.ant3-form-item-label) {
        width: 100px;
        white-space: break-spaces;
        text-align: center;
    }
    .story-name-select:deep(.ant3-form-item-control) {
        overflow: hidden;
    }
    .story-name-select:deep(.ant3-form-item) {
        display: flex !important;
        flex-wrap: nowrap !important;
    }
    .story-name-select:deep(.ant3-form-item-label) {
        width: 100px !important;
        flex-shrink: 0;
    }
    .top-search :deep(.ant3-form-item-label > label) {
        height: 35px !important;
    }
    .top-search {
        background-color: #fff;
    }
    .top-search :deep(.ant3-row) {
        height: 40px;
    }
    .top-search :deep(.ant3-col) {
        height: 40px;
    }
    .mt-4 {
        margin: 0;
    }
    .content {
        background-color: #fff;
        padding: 8px 16px 16px 16px;
        height: 100%;
    }
    .table-top {
        display: flex;
        justify-content: space-between;
        margin-bottom: 16px;
        margin-top: 12px;
        align-items: center;
    }
    .tip-msg {
        padding-left: 8px;
        border-left: 4px solid #3875ff;
        height: 16px;
        font-size: 16px;
        font-weight: 600;
        line-height: 16px;
    }
    .right-btn {
        display: flex;
        gap: 8px;
    }

    .form-model :deep(.ant3-form-item-label) {
        width: 110px;
    }
    :deep(.ql-toolbar) {
        background: #fafafa;
        border: 1px solid #d9d9d9;
        border-radius: 2px 2px 0 0;
    }
    :deep(.ql-blank) {
        min-height: 110px;
        background: #ffffff;
    }
    :deep(.ql-editor) {
        min-height: 110px;
        background: #ffffff;
    }
    .table-box-task:deep(
            .ant3-table.ant3-table-bordered > .ant3-table-container > .ant3-table-content > table > tbody > tr > td
        ) {
        padding: 8px 16px;
    }
    .correlation-box:deep(
            .ant3-table.ant3-table-bordered > .ant3-table-container > .ant3-table-content > table > tbody > tr > td
        ) {
        padding: 8px 16px;
    }
    .table-box-story:deep(
            .ant3-table.ant3-table-bordered.ant3-table-small
                > .ant3-table-container
                > .ant3-table-body
                > table
                > tbody
                > tr
                > td
                > .ant3-table-expanded-row-fixed
        ) {
        padding-left: 22px !important;
        padding-bottom: 5px !important;
    }
    .table-box-story:deep(.ant3-table-expanded-row-fixed) {
        padding: 0;
    }
    .mbtask-form :deep(.ant3-form-item-label) {
        width: 115px !important;
    }
    .type-tag {
        flex-shrink: 0;
        text-align: left;
        border-radius: 4px;
        padding: 0 4px;
    }
    .task-title {
        display: flex;
        gap: 4px;
        background: linear-gradient(to bottom, rgba(255, 255, 255, 0.92), #fff, #fff);
        align-items: center;
    }
    .name-color,
    .story-name-color {
        color: #262626;
    }
    .story-name-color {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    .priority-tag {
        font-style: oblique;
        background: #ccc;
        border-radius: 0;
        font-size: 14px;
        color: #ffffff;
        letter-spacing: 0;
        line-height: 22px;
        font-weight: 500;
        height: 22px;
        text-align: center;
        padding: 0 8px; /* 可根据内容调整内边距 */

        /* 自动根据内容撑开宽度 */
        display: inline-flex;
        justify-content: center;
        align-items: center;
    }

    .status-tag {
        font-size: 14px;
        color: #ffffff;
        letter-spacing: 0;
        text-align: center;
        line-height: 22px;
        font-weight: 500;
        width: 55px;
        height: 22px;
        border-radius: 2px;
        flex: 1;
    }
    .edit-approve {
        box-shadow: rgb(193, 205, 223) 0px 2px 6px;
        text-align: right;
        display: flex;
    }
    .can-edit {
        width: 16px;
        height: 16px;
        background-image: url('http://10.40.0.33:9001/file-storage/523231194136260608-source.png');
        background-size: cover;
        opacity: 0.7;
        cursor: pointer;
    }
    .question-form :deep(.ant3-form-item-label) {
        width: 115px !important;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        display: inline-block;
    }
    .critical-path {
        height: 20px;
        width: 20px;
        background-image: url('http://10.40.0.33:9001/file-storage/528348581051316224-source.png');
        background-size: cover;
        flex-shrink: 0;
    }
    .story-status {
        margin: 0 auto;
    }
    .story-bg {
        height: 24px;
        width: 24px;
        background-image: url('http://10.40.0.33:9001/file-storage/527026039625691136-source.png');
        background-size: cover;
    }
    .sop-task-bg {
        height: 24px;
        width: 24px;
        background-image: url('http://10.40.0.33:9001/file-storage/527026395994730496-source.png');
        background-size: cover;
    }
    .son-task-bg {
        height: 24px;
        width: 24px;
        background-image: url('http://10.40.0.33:9001/file-storage/527026489932460032-source.png');
        background-size: cover;
    }
    .question-task-bg {
        height: 24px;
        width: 24px;
        background-image: url('http://10.40.0.33:9001/file-storage/527026529524592640-source.png');
        background-size: cover;
    }
    /*样式*/

    .title-new-status {
        height: 62px;
        line-height: 36px;
        padding: 0 16px;
        margin-bottom: 16px;
        background-image: url('http://10.40.0.33:9001/file-storage/447701084442329088-source.png');
        background-size: cover;
        border: 1px solid #3875ff;
        border-radius: 5px;
    }

    :deep(.ant3-steps-item-container) {
        padding: 0 16px;
    }
    :deep(.ant3-steps-item-tail::after) {
        margin-left: 12px;
        background-color: #3875ff;
    }
    :deep(.ant3-steps-item-description) {
        font-size: 12px;
        color: #595959;
        text-align: left;
        line-height: 20px;
        font-weight: 400;
    }
    :deep(.ant3-steps-item-icon) {
        width: 24px;
        height: 24px;
        line-height: 24px;
        color: #3875ff;
        margin-top: 6px;
    }
    :deep(.ant3-steps-item-title) {
        height: 28px;
        font-size: 14px;
        color: #262626;
        text-align: left;
        line-height: 22px;
        font-weight: 400;
    }
    :deep(.ant3-steps-item-process > .ant3-steps-item-container > .ant3-steps-item-icon) {
        background-color: #3875ff;
    }
    :deep(.ant3-steps-vertical > .ant3-steps-item > .ant3-steps-item-container > .ant3-steps-item-tail::after) {
        background: #3875ff;
    }
    :deep(.status-step .ant3-steps-vertical > .ant3-steps-item .ant3-steps-item-icon) {
        border-color: #3875ff;
    }
    :deep(.ant3-steps-item-finish .ant3-steps-item-icon > .ant3-steps-icon) {
        color: #3875ff !important;
    }
    .task-status-new {
        cursor: pointer;
    }
    .left-title,
    .right-title {
        font-size: 14px;
        color: rgba(0, 0, 0, 0.65);
        letter-spacing: 0;
        text-align: left;
        font-weight: 400;
        height: 31px;
        line-height: 31px;
    }
    .weight-status {
        font-size: 14px;
        color: #262626;
        letter-spacing: 0;
        font-weight: 500;
    }
    .batch-line {
        width: 100%;
        border-top: 1px solid #d9d9d9;
        margin: 16px 0;
    }
    .weight-status-new {
        font-weight: 600;
        color: #262626;
    }
    .task-collaborate {
        width: 58px;
        text-align: center;
        height: 16px;
        line-height: 16px;
        position: absolute;
        top: 12px;
        left: 9px;
        background-color: #eee5fa;
        color: #9254de;
    }
    .task-name-title-right {
        margin-left: 80px;
    }
    .name-color:hover,
    .story-name-color:hover {
        cursor: pointer;
        color: #3875ff;
    }
    .description-title {
        font-weight: 600;
        margin-bottom: 8px;
        border-left: 4px solid #3875ff;
        padding-left: 6px;
        height: 14px;
        line-height: 14px;
    }
    /* 外层允许小屏水平滚动 */
    .desc-wrapper {
        width: 100%;
        overflow-x: auto;
    }
    .desc-table {
        margin-bottom: 8px;
    }
    /* 表格样式：实线、单元格对齐、固定 label 宽度 */
    .desc-table {
        width: 100%;
        border-collapse: collapse;
        table-layout: fixed; /* 让列按 colgroup 分配宽度 */
        font-size: 13px;
    }

    .desc-table th,
    .desc-table td {
        border: 1px solid #e8e8e8;
        padding: 10px 12px;
        vertical-align: middle;
        background: #fff;
        box-sizing: border-box;
    }

    /* label 样式（左侧） */
    .desc-table th {
        background: #f2f6fc;
        font-weight: 600;
        text-align: left;
        white-space: nowrap; /* label 不换行 */
        writing-mode: horizontal-tb !important; /* 防止被全局样式转成竖排 */
        transform: none !important;
    }

    /* value 栏：支持换行但太长时不撑破布局（单元格内部换行） */
    .desc-table td {
        white-space: normal;
        word-break: break-word;
        overflow: hidden;
    }

    /* 当你希望某些长文本一行显示并省略（可按需打开） */

    .desc-table td.single-line {
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    .description-body {
        margin-bottom: 8px;
    }
    .story-header {
        position: relative;
    }
    .expend-btn {
        position: absolute;
        top: 10px;
        left: 10px; /* 往左偏移 */
        z-index: 20; /* 高于表格单元格 */
        cursor: pointer;
    }
    .table-box-story {
        position: relative;
    }
    .history-remark-title {
        display: flex;
        justify-content: end;
        margin-bottom: 16px;
    }
    .transfer-tip {
        font-size: 12px;
        letter-spacing: 0;
        text-align: justify;
        font-weight: 400;
        color: #ff8022;
        background: rgba(250, 100, 0, 0.05);
        padding: 6px 16px;
        margin-right: 8px;
    }
    .story-task-name {
        color: #3875ff;
    }
    .table-title {
        padding-left: 8px;
        border-left: 4px solid #3875ff;
        height: 14px;
        margin: 16px 0;
        line-height: 14px;
        font-weight: 600;
    }
    .correlation-box {
        margin-bottom: 16px;
    }
</style>
